返回捕获局部变量的lambda

时间:2017-05-17 01:52:22

标签: c++ c++11 lambda currying

今天我在C ++ 11 lambdas中遇到了一个非常不直观的行为(至少对我来说)。有问题的代码如下:

#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 ++中进行currying,保证变量被正确捕获?

1 个答案:

答案 0 :(得分:8)

int x的有效期有限。对自动存储变量(您称之为“堆栈”)的引用仅对变量的生命周期有效。在这种情况下,只有在存在变量的堆栈帧(范围)的末尾或函数参数的函数之前。

[&]通过引用捕获任何提到的(“本地”)变量,但this除外(如果使用或隐式使用,则由值捕获)。 [=]按值捕获任何提到的变量。 [x]将明确地捕获x,并通过引用明确捕获[&x]。在C ++ 17中,[*this]也可以。

还有[x=std::move(x)][blah=expression]

一般情况下,如果lambda将比当前范围更长,则不要使用[&]:明确你捕获的内容。