按价值捕获

如果在捕获列表中指定变量的名称,则 lambda 将按值捕获它。这意味着为 lambda 生成的闭包类型存储变量的副本。这也要求变量的类型是可复制构造的

int a = 0;

[a]() {
    return a;   // Ok, 'a' is captured by value
};

Version < C++ 14

auto p = std::unique_ptr<T>(...);

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

从 C++ 14 开始,可以在现场初始化变量。这允许仅在 lambda 中捕获移动类型。

Version >= C++ 14

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

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

即使 lambda 在按名称给出时按值捕获变量,默认情况下也不能在 lambda 体内修改这些变量。这是因为闭包类型将 lambda 主体放在 operator() const 的声明中。

const 适用于对闭包类型的成员变量的访问,以及作为闭包成员的捕获变量(所有外观相反):

int a = 0;

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

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

要删除 const,你必须在 lambda 上指定关键字 mutable

int a = 0;

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

因为 a 是按值捕获的,所以通过调用 lambda 进行的任何修改都不会影响 aa 的值在构造时被复制到 lambda 中,因此 a 的 lambda 副本与外部 a 变量分开。

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"