类 lambda 和捕获这个

在类的成员函数中计算的 lambda 表达式隐式地是该类的朋友:

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);
    }
};

这样的 lambda 不仅是该类的朋友,它具有与其声明的类相同的访问权限。

Lambdas 可以捕获 this 指针,该指针表示调用外部函数的对象实例。这是通过将 this 添加到捕获列表来完成的:

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);
    }
};

当捕获 this 时,lambda 可以使用其包含类的成员名称,就像它在其包含的类中一样。所以隐含的 this-> 应用于这些成员。

请注意,this 是按值捕获的,而不是类型的值。它由 this 的值捕获,this 是一个指针。因此,lambda 不拥有 this。如果 lambda out 存在于创建它的对象的生命周期中,则 lambda 可能变为无效。

这也意味着 lambda 可以修改 this 而不会被声明为 mutable。它是 const 的指针,而不是指向的对象。也就是说,除非外部成员函数本身就是一个 const 函数。

另外,请注意默认捕获子句 [=][&] 将隐式捕获 this。它们都通过指针的值捕获它。实际上,当给出默认值时,在捕获列表中指定 this 是错误的。

Version >= C++ 17

Lambdas 可以捕获创建 lambda 时创建的 this 对象的副本。这是通过将*this 添加到捕获列表来完成的:

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
    }
};