2016-03-20 19 views
1

In C++ gibt es eine bevorzugte Möglichkeit, mit einer rekursiven Funktion umzugehen, die jedes Mal ein unverändertes Objekt wiederverwendet? Zum Beispiel (Pseudocode):Rekursive Funktionen mit konstanten Parametern

void func(HashMap h, Logger logger, int depth) 
{ 
    // Do stuff then call func recursively... 
    func(h, logger, depth+1); 
} 

Also jeder Aufruf, den wir in mehreren Objekten (Hash-Karte und Logger) unverändert übergeben. Ja, wir können durch Verweis gehen, aber es scheint immer noch ineffizient und sieht nicht sehr hübsch aus. Die einzige Alternative, die ich mir vorstellen kann, sind globale Variablen oder die Bündelung der konstanten Parameter in einer Struktur.

+2

Nun, es gibt Gründe, warum es verschiedene Sprachen gibt. Sie alle spezialisieren sich auf verschiedene Anwendungsfälle und haben grundlegende Unterschiede. Die optimale Lösung für eine bestimmte Sprache ist möglicherweise nicht die beste Lösung für eine andere Sprache. –

+0

In C++ bündeln Sie die konstanten Parameter in einer Struktur und übergeben Sie sie als Referenz –

+0

"Ja, wir können durch Verweis gehen, aber es scheint immer noch ineffizient", bitte erklären? – txtechhelp

Antwort

0

Dies ist perfekt sauberer Code, der genau das ausdrückt, was passiert. Natürlich sollten Sie in C++ die HashMap und den Logger als const-Referenz übergeben.

Aus der Sicht der Leistung, jedoch könnte es besser sein, diese beiden Objekte Klassenvariablen zu machen. Dies könnte jedoch den Code schwerer verständlich machen, also tun Sie es einfach, wenn Sie wirklich ein Leistungsproblem haben.

Übrigens, was macht die Funktion, wenn sie die HashMap nicht ändert und void zurückgibt?

+0

In meinem Fall wurde die Hashmap nur gelesen und lieferte einige Nachschlagevorgänge für die Verarbeitung in der rekursiven Funktion. – SteevieP

+0

@steevieP: Also ist der Haupteffekt der Funktion tatsächlich ein Nebeneffekt? Dies wird normalerweise nicht als gutes Design angesehen, insbesondere für eine rekursive Funktion. –

0

Was Sie beschreiben, ist eine geschlossene lexikalische Umgebung, auch bekannt als "Schließung". Dieses Konzept existiert "kostenlos" in dynamischen Sprachen wie Lisp und Scheme, wo das "let over lambda" -Muster es erlaubt, Variablen in einer Funktion zu erfassen und sie zu verwenden, auch wenn ihr einschließender Gültigkeitsbereich verlassen oder verlassen ist.

Sie können Schließungen in C++ mit einem struct als Container für die erfassten Variablen simulieren und Funktionen (Funktoren) auf die struct anwenden. Das häufigste Muster hierfür ist in der Regel die Art und Weise, dass operator() verwendet wird:

struct my_closure { 
    Hashmap &hmap_; 
    Logger &logger_; 
    int depth_; 

    my_closure(Hashmap &hmap, Logger &logger, int depth) : 
    hmap_(hmap), logger_(logger), depth_(depth) 
    { } 

    void operator()(void) 
    { /* do stuff here, including recurse */ } 
}; 

Das einzige, was dies erspart wird Ihnen zusätzliche Material auf den Stapel schieben, die nicht notwendigerweise Sie viel in Bezug auf Zyklen sparen (1 Strukturreferenz [this Zeiger für die Struktur] vs. 2 Referenzen + 1 Ganzzahl.) Wenn Ihr Compiler Tail-Rekursion unterstützt, könnte dies ein Vorteil auf Kosten der Lesbarkeit sein.

+0

C++ 11 unterstützt Verschlüsse. Sie müssen also keine dedizierte Struktur (mit einem albernen Namen) mehr erstellen. –

+0

@FrankPuffer: Es ist nützlich, zu verstehen, wie man einen erstellt, wenn Ihnen die Maschinen von C++ 11 nicht zur Verfügung stehen. Insofern, dass das Verstehen von Zeigern auf Funktionen darin besteht, virtuelle Funktionen zu implementieren. –

Verwandte Themen