2016-06-26 5 views
4

ich eine grundlegende Lambda haben, die wie folgt aussieht:Wie können C++ - Lambdas den inneren Zustand beibehalten?

auto l = [](){ 
    int i = 0; 
    cout << i++; 
} 

ein paar Mal diese aufrufen, halten 0. Drucken Wie kann ich ich behalten? Kann ich das ohne Funktoren machen?

+3

Wie können Funktionen den inneren Zustand beibehalten? – LogicStuff

+2

Vielleicht brauchst du 'statisch'? –

Antwort

4
auto l = [](){ 
    static int i = 0; 
// ^^^^^^ 
    cout << i++; 
} 

sollte Ihre Bedenken beheben.

Im Allgemeinen können Funktionen inneren Zustand nicht beibehalten, ohne eine lokale static Variable zu verwenden. Es gibt keinen Unterschied zur tatsächlichen Verwendung von Lambda.


Wenn Sie Kopien zählen möchten, können Sie eine gewöhnliche Funktors Klassenimplementierung als @Revolver_Ocelot suggested verwenden.

+0

nur als eine Nebenfrage, wenn ich eine Kopie von l machen möchte, würde diese Kopie nicht die gleiche Variable wie ich behalten? – val

+1

@val Ja, es würde es behalten, da Lambdas des gleichen Typs alle diese Instanz von "i" teilen. –

+0

Gibt es eine Möglichkeit, dass jede Instanz von l ihre eigene Version von i haben kann, mit der sie arbeiten können? – val

2

Wenn Sie i wollen ihren Wert behalten, dann haben Sie drei Möglichkeiten:

  1. Deklarieren i als globale Variable (Bad).
  2. Pässe vorheriger Wert von i auf die Funktion jedes Mal (sehr gut).
  3. Deklarieren i als static Variable (am besten).

    auto l = []() { static int i = 0; cout << i++ << endl; }; 
    l(); l(); l(); 
    

    Dies als Ausgabe geben wird:

    0 
    1 
    2 
    
+4

Ich bin mir nicht sicher, dass statische == am besten. Eine Statik ist unmöglich zu kontrollieren. –

+1

"statisch" bedeutet auch einen Mangel an Fadensicherheit. – DiB

9

Versuchen Sie, denken Sie an eine Lambda als eine Klasse mit einem operator(). Wie würdest du den Status in einer Klasse behalten? Habe ein Mitglied. Captures sind hier gleichbedeutend.

#include <iostream> 
auto l = [i=0]()mutable{ 
    std::cout << i++; 
}; 
auto l2=l; 
int main(){ 
    l(); // 0 
    l(); // 1 
    l(); // 2 
    l2(); // 0 
    l2(); // 1 
    l(); // 3 
    std::cout << '\n'; 
} 
11

Je nachdem, was Sie mit diesem Lambda tun möchten, können Sie die folgende Alternative betrachten:

auto exec = [i = 0]() mutable { cout << ++i << ' '; }; 
exec(); // 1 
exec(); // 2 
auto exec2 = exec; // copy state of lambda 
exec2(); // 3 
exec(); // 3 

Mit []() { static int i = 0; cout << ++i << ' '; }; stattdessen in der Folge führen 1 2 3 4 gedruckt wird.

Live example

+4

Bitte beachten Sie: erforderlich C++ 14. – md5i

+0

Ja, wollte sagen, es kompiliert nicht auf VS2013. – val

Verwandte Themen