我无法理解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();
}
};
Run Code Online (Sandbox Code Playgroud)
注意:唯一的区别在于x变量的位置; ClassA和ClassB的功能有不同的输出!
A 1
A 1
B 1
B 2
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:
谢谢
Mik*_*our 11
第一个x按值捕获局部变量; 所以它打印1两次,因为它的副本没有改变.
第二个捕获本地准变量this,而不是成员变量x.所以身体是等同的printf("%d\n", this->x);,并且会2在你改变之后打印出新的价值x.
如果您要明确捕获x(即[x](){...}),那么您将看到与第一个相同的结果.
这是理想的行为吗?
这是语言标准指定的行为.
如果我在ClassA中使用[&]而不是[=],那些lambdas是否相同?
不,但两者都会产生相同的输出.第一个将x通过引用捕获本地,因此您将看到对它的更改.
是否有一些关于何时[=]实际制作副本的一般规则?
是的,它在创建lambda时复制变量.
究竟是什么时候应该发生lambda的变量捕获?
当lambda被创建时.
我可以强制lambda重新捕获变量吗?
不会.一旦它被值捕获,它就有自己的变量副本,无法访问原始变量.如果您需要查看原始更改,请通过引用捕获(并注意对象生存期).