今天我在 C++11 lambda 中遇到了一个非常不直观的行为(至少对我而言)。有问题的代码如下:
#include <stdio.h>
auto sum(int x) {
return [&x](int y) {
return x + y;
};
}
int main() {
int a = sum(2)(3);
printf("%d\n",a);
}
这不是打印 5,而是乱码。实际上,至少在我的 GCC 版本中,如果我打开 -O2 优化标志,它实际上会打印 5。由于输出取决于编译器的优化级别,因此它是未定义的行为。过了一会儿,我想我明白发生了什么。
当函数sum被调用时,参数x对应的一个栈变量被设置为2,然后函数sum返回,这个栈变量可能会被编译器需要放在那里的任何东西覆盖以执行下面的代码,到 lambda 最终被执行时,x 所在的位置不再包含 2,程序将 3 添加到任意整数。
在 C++ 中是否有任何优雅的方式来保证变量被正确捕获?
最佳答案
int x
的生命周期有限。对自动存储变量(您称之为“堆栈”)的引用仅在变量的生命周期内有效。在这种情况下,仅直到变量存在的堆栈帧(作用域)或函数参数的函数结束。
[&]
通过引用捕获任何提到的(“本地”)变量,this
除外(如果使用或隐式使用,则按值捕获)。 [=]
按值捕获任何提到的变量。 [x]
将显式捕获 x
,并通过引用显式捕获 [&x]
。在 C++17 中,[*this]
也有效。
还有[x=std::move(x)]
,或者[blah=expression]
。
一般来说,如果 lambda 将比当前作用域更有效,请不要使用 [&]
:明确说明您捕获的内容。
关于c++ - 返回捕获局部变量的 lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54812194/