C++ Cattura in base al valore


Esempio

Se si specifica il nome della variabile nella lista di cattura, lambda la catturerà per valore. Ciò significa che il tipo di chiusura generato per il lambda memorizza una copia della variabile. Ciò richiede anche che il tipo della variabile sia copy-constructible :

int a = 0;

[a]() {
    return a;   // Ok, 'a' is captured by value
};
C ++ 14
auto p = std::unique_ptr<T>(...);

[p]() {         // Compile error; `unique_ptr` is not copy-constructible
    return p->createWidget(); 
};

Da C ++ 14 in poi, è possibile inizializzare le variabili sul posto. Ciò consente di spostare solo i tipi da catturare nella lambda.

C ++ 14
auto p = std::make_unique<T>(...);

[p = std::move(p)]() {
    return p->createWidget(); 
};

Anche se un lambda cattura le variabili in base al valore quando sono date dal loro nome, tali variabili non possono essere modificate all'interno del corpo lambda di default. Questo perché il tipo di chiusura inserisce il corpo lambda in una dichiarazione di operator() const .

Il const applica agli accessi alle variabili membro del tipo di chiusura e alle variabili catturate che sono membri della chiusura (tutte le apparenze in contrario):

int a = 0;

[a]() {
    a = 2;      // Illegal, 'a' is accessed via `const`

    decltype(a) a1 = 1; 
    a1 = 2; // valid: variable 'a1' is not const
};

Per rimuovere il const , devi specificare la parola chiave mutable sul lambda:

int a = 0;

[a]() mutable {
    a = 2;      // OK, 'a' can be modified
    return a;
};

Poiché a stato catturato dal valore, qualsiasi modifica eseguita chiamando lambda non influirà su a . Il valore di a stato copiato nella lambda quando è stato costruito, in modo copia del lambda di a separato dall'esterno a variabile.

int a = 5 ; 
auto plus5Val = [a] (void) { return a + 5 ; } ; 
auto plus5Ref = [&a] (void) {return a + 5 ; } ; 

a = 7 ; 
std::cout << a << ", value " << plus5Val() << ", reference " << plus5Ref() ;
// The result will be "7, value 10, reference 12"