C++ Classe lambda e cattura di questo


Esempio

Un'espressione lambda valutata in una funzione membro della classe è implicitamente un amico di quella classe:

class Foo
{
private:
    int i;
    
public:
    Foo(int val) : i(val) {}
    
    // definition of a member function
    void Test()
    {
        auto lamb = [](Foo &foo, int val)
        {
            // modification of a private member variable
            foo.i = val;
        };
        
        // lamb is allowed to access a private member, because it is a friend of Foo
        lamb(*this, 30);
    }
};

Tale lambda non è solo un amico di quella classe, ha lo stesso accesso della classe dichiarata all'interno.

Lambda possono catturare this puntatore che rappresenta l'istanza oggetto la funzione esterno era chiamato. Questo viene fatto aggiungendo this alla lista di cattura:

class Foo
{
private:
    int i;
    
public:
    Foo(int val) : i(val) {}
    
    void Test()
    {
        // capture the this pointer by value
        auto lamb = [this](int val)
        {
            i = val;
        };
        
        lamb(30);
    }
};

Quando this viene catturato, il lambda può usare i nomi dei membri della sua classe contenente come se fosse nella sua classe contenente. Quindi un implicito this-> è applicato a tali membri.

Si noti che this viene catturato dal valore, ma non dal valore del tipo. Viene catturato dal valore di this , che è un puntatore . In quanto tale, il lambda non possiede this . Se il lambda out vive la vita dell'oggetto che lo ha creato, il lambda può diventare non valido.

Questo significa anche che la lambda può modificare this senza essere dichiarato mutable . È il puntatore che è const , non l'oggetto puntato. Cioè, a meno che la funzione membro esterno fosse di per sé una funzione const .

Inoltre, tieni presente che le clausole di acquisizione predefinite, sia [=] che [&] , cattureranno anche this implicitamente. E entrambi lo catturano per il valore del puntatore. In effetti, si tratta di un errore di specificare this nella lista di cattura quando viene dato un valore predefinito.

C ++ 17

Lambdas può catturare una copia di this oggetto, creata nel momento in cui viene creata la lambda. Questo viene fatto aggiungendo *this alla lista di cattura:

class Foo
{
private:
    int i;
    
public:
    Foo(int val) : i(val) {}
    
    void Test()
    {
        // capture a copy of the object given by the this pointer
        auto lamb = [*this](int val) mutable
        {
            i = val;
        };
        
        lamb(30); // does not change this->i
    }
};