按价值捕获
如果在捕获列表中指定变量的名称,则 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 进行的任何修改都不会影响 a
。a
的值在构造时被复制到 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"