我正在阅读本书第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;
Run Code Online (Sandbox Code Playgroud)
这段代码打印出来:
x: 0
y: 77
x: 0
y: 78
final y: 79
Run Code Online (Sandbox Code Playgroud)
为什么qqq()没有注册x已经改为77?据说,通过值传递意味着我们可以读取但不能修改定义lambda的数据.这是否意味着我们在定义后无法看到变化?
vso*_*tco 19
这是因为当你定义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();
}
Run Code Online (Sandbox Code Playgroud)
344*_*442 11
通过将值变量绑定到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;
}
Run Code Online (Sandbox Code Playgroud)
是(种类,但不完全)语法糖...
#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;
}
Run Code Online (Sandbox Code Playgroud)
除了特殊的lambda语法和你不能直接引用lambda类型的事实.通过将前者与后面的代码进行比较,您应该能够清除对闭包的理解.
| 归档时间: |
|
| 查看次数: |
7983 次 |
| 最近记录: |