[英]c++ lambda capture by value
我正在閱讀本書第3章中的C ++ lambda部分,以下代碼讓我困惑:
int x = 0;
int y = 42;
auto qqq = [x, &y] {
std::cout << "x: " << x << std::endl;
std::cout << "y: " << y << std::endl;
++y;
};
x = y = 77;
qqq();
qqq();
std::cout << "final y: " << y << std::endl;
這段代碼打印出來:
x: 0
y: 77
x: 0
y: 78
final y: 79
為什么qqq()沒有注冊x已經改為77? 據說,通過值傳遞意味着我們可以讀取但不能修改定義lambda的數據。 這是否意味着我們在定義后無法看到變化?
這是因為當你定義lambda時,變量只被值(即復制)捕獲一次。 它可能不會像您所認為的那樣“更新”。 代碼大致相當於:
#include <iostream>
int x = 0;
struct Lambda
{
int _internal_x; // this is used to "capture" x ONLY ONCE
Lambda(): _internal_x(x) {} // we "capture" it at construction, no updates after
void operator()() const
{
std::cout << _internal_x << std::endl;
}
} qqq;
int main()
{
qqq();
x = 77; // this has no effect on the internal state of the lambda
qqq();
}
通過將值變量綁定到lambda閉包,您可以有效地將變量的值復制到lambda對象中的單獨變量中。 同樣,通過引用綁定變量,您將使這樣的內部變量成為對原始變量的引用,從而能夠“看到原始變量的變化”。
像這樣看待它。 以下代碼......
#include <iostream>
int main()
{
int x = 0;
int y = 42;
auto qqq = [x, &y] {
std::cout << "x: " << x << std::endl;
std::cout << "y: " << y << std::endl;
++y;
};
x = y = 77;
qqq();
qqq();
std::cout << "final y: " << y << std::endl;
}
是(種類,但不完全)語法糖...
#include <iostream>
class MyLambda
{
private:
int x;
int& y;
public:
MyLambda(int x, int& y) : x(x), y(y) {}
void operator()()
{
std::cout << "x: " << x << std::endl;
std::cout << "y: " << y << std::endl;
++y;
}
};
int main()
{
int x = 0;
int y = 42;
MyLambda qqq = MyLambda(x, y);
x = y = 77;
qqq();
qqq();
std::cout << "final y: " << y << std::endl;
}
除了特殊的lambda語法和你不能直接引用lambda類型的事實。 通過將前者與后面的代碼進行比較,您應該能夠清除對閉包的理解。
lambda使用lambda定義時的值(它創建一個副本),而不是在調用它時。
這可能有所幫助: Lambda Closures如何實現?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.