c++ - 返回捕获局部变量的 lambda

标签 c++ c++11 lambda currying

今天我在 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/

相关文章:

c++ - 即使可执行文件的输入是从文件重定向的,如何强制从终端输入?

c# - 如何从 C# 调用带有结构指针参数的 C++ 函数?

c++ - std::thread --- 没有匹配的构造函数

c# - lambda 字符串按日期和数字排序

c# - List<string> 复杂排序

c++ - 我如何制作 lambda 函数的原型(prototype)?

c++ - OpenGL 非独占全屏模式(又名全屏无边框窗口)

c++ - C++ 中的条件表达式总是 bool 类型吗?

c++ - 测试 boost::mpl::or_ 的计算结果是真还是假

c++ - 如何在 C++11 的迭代器中获取有关 auto 标识符的更多详细信息