按價值捕獲
如果在捕獲列表中指定變數的名稱,則 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"