2017-02-05 2 views
4

Die Notwendigkeit des Schlüsselwortes mutable in Lambdas, ist Quelle für große Verwirrung.Lambda-Capture nach Wert und das "veränderbare" Schlüsselwort

Betrachten Sie den Code:

int x = 10; 

function<void()> lambda = [=]() mutable {x++; cout << "Inside lambda: x = " << x << "\n";}; 

cout << "Before lambda: x = " << x << "\n"; 
lambda(); 
cout << "After lambda: x = " << x << "\n\n"; 

Ausgang:

Before lambda: x = 10 
Inside lambda: x = 11 
After lambda: x = 10 

Wie wir die variablen x bleibt unverändert nach dem Lambda sehen können, so gibt es keine Nebenwirkungen.

Wenn wir jedoch das Schlüsselwort veränderbar "vergessen", erhalten wir einen Fehler.

Da das Argument den Wert in C++ übergibt, macht es keinen Sinn für das veränderbare Schlüsselwort.

Kann jemand (auch im Pseudocode) die vom Compiler erzeugte Klasse anstelle des Lambda schreiben?

Danke

+0

Mögliches Duplikat von [C++ 0x Lambda Capture nach Wert immer const?] (Http: // stackoverflow.com/questions/2835626/c0x-lambda-capture-by-wert-immer-const) – LogicStuff

Antwort

1
class Lambda 
{ 
public: 
    Lambda(const Lambda&); 
    ~Lambda(); 

    // the main functor operator, const when lambda not mutable 
    R operator()(Args args) const; 

    // Only present for non-capture lambda   
    operator PlainCFunctionType() const; 

    // Only present for non-capture lambda   
    PlainCFunctionType operator+() const; 
private: 
    // Gets called when lambda created, but you can't call it yourself 
    Lambda(Captures captures...); 

    Captures captures; 
}; 
1

Du wirklich keinen Code in einer objektorientierten Art und Weise zu schreiben, aber trotzdem. Normalerweise sind die externen Variablen, die durch [=] hinzugefügt werden, konstante Werte. Wenn Sie das Schlüsselwort mutable hinzufügen, erstellen Sie lokal änderbare Kopien von ihnen. Sie könnten stattdessen [&] verwenden, um durch Referenz zu erfassen.

+0

Mit [&] ändern Sie den Variablenwert nach dem Lambda. In meinem Code ist die Erfassung nach Wert. –

4

Wie erwähnt here der mutable Spezifizierer das Lambda kann die Parameter durch Kopieren erfaßt ändern und ihre nicht-const Funktionen Mitglied anrufen. Es hat keine Auswirkungen auf Variablen, die durch Referenz erfasst werden.

Kann jemand (auch im Pseudocode) die vom Compiler erzeugte Klasse anstelle des Lambda schreiben?

Es ist nicht so einfach, einen allgemeinen Fall anzugeben, aber wir können etwas definieren, das in Ihrem speziellen Fall gültig ist.
Die generierte Klasse wohl aussehen würde:

struct Lambda { 
    void operator()() { x++; } 
    int x{10}; 
}; 

Wenn Sie die mutable Spezifizierer entfernen, wird die Funktion Operator als const definiert:

struct Lambda { 
    void operator()() const { x++; } 
    int x{10}; 
}; 

Der Einfachheit halber ich x mit dem angegebenen Wert initialisiert habe (10) und es öffentlich gemacht, aber es wird offensichtlich durch Kopieren initialisiert, indem die Variable verwendet wird, die aus dem umgebenden Kontext erfasst wurde und von außerhalb des Funktionsoperators nicht zugänglich ist.
Seine Art ist auch aus der Variablen verwendet abgeleitet es zu initialisieren, als ob Sie tun:

auto lambda_x = x; 

here für weitere Details.

Verwandte Themen