我无法理解 lambda 函数和捕获变量的机制,所以我做了一些测试并得出了非常奇怪的结论。即:
class ClassA
{
public:
std::function<void()> lambda;
void DoYourStuff()
{
int x;
x = 1;
lambda = [=] () { printf("A %d\n", x);};
lambda();
x = 2;
lambda();
}
};
class ClassB
{
public:
std::function<void()> lambda;
int x;
void DoYourStuff()
{
x = 1;
lambda = [=] () { printf("B %d\n", x);};
lambda();
x = 2;
lambda();
}
};
注意:唯一不同的是 x 变量的位置; ClassA 和 ClassB 的函数有不同的输出!
A 1
A 1
B 1
B 2
所以我的问题是:
- 这是期望的行为吗?
- 如果我在 ClassA 中使用 [&] 而不是 [=],这些 lambda 是否相同?
- 关于 [=] 实际复制的时间是否有一些通用规则?
- lambda 捕获变量的确切时间应该在什么时候发生?
- 我可以强制 lambda 重新捕获变量吗?
谢谢
最佳答案
第一个按值捕获局部变量x
;所以它两次打印 1
,因为它的拷贝没有改变。
第二个捕获局部准变量this
,不是成员变量x
。所以正文等价于 printf("%d\n", this->x);
,并且会在你更改 后打印
.2
的新值x
如果您要显式捕获 x
(即 [x](){...}
),那么您将看到与第一个相同的结果。
Is this the desired behaviour?
这是语言标准规定的行为。
if i used [&] instead of [=] in ClassA, would those lambdas be identical?
不,但两者会产生相同的输出。第一个将通过引用捕获本地 x
,因此您将看到对其的更改。
Is there some general rule as to when [=] actually makes copy?
是的,它会在创建 lambda 时复制变量。
When exactly is the capturing of variables by lambdas supposed to happen?
创建 lambda 时。
Can I force lambda to do a re-capture of variables?
没有。一旦它被值捕获,它就有了自己的变量拷贝,无法访问原始变量。如果您需要查看对原始文件的更改,则通过引用捕获(并注意对象生命周期)。
关于c++ - lambda 的捕获机制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12622627/