繁体   English   中英

Lambda变量捕获

[英]Lambda variable capture

我对lambda表达式的变量捕获部分的性质感到困惑。

void f1();
std::function<int()> f2;

int main() {
    f1();
    std::cout<<f2()<<endl;
}

void f1() {
    int x;
    f2 = [&]() {
        return x;
    };
}

在调用f2之前x不会被解构吗?

是。 您已成功调用未定义的行为。 一种可能的结果是您得到x的值。 另一个原因是计算机格式化了硬盘驱动器,程序崩溃或计算机变成了自动烘烤面包机的刺客,为您提供蛋糕,错误地认为您患有乳糜泻。

一个安全的变体可能是:

int main() {
    f1(7);
    std::cout<<f2()<<endl;
}

void f1(int x) {
    std::shared_ptr<int> spX( new int(x) );
    f2 = [=]() {
        return *spX;
    };
}

要么

void f1(int x) {
    f2 = [=]() {
        return x;
    };
}

(对于int,没有理由不按值存储它:对于更复杂的类型,您可能要避免不必要地对其进行复制)。

请注意,上面的注释以更有趣的方式说明了这一点。

现在,当您递减堆栈以恰好捕获这种未定义的行为时,某些编译器将使用特殊值标记堆栈(通过catch,我的意思是使堆栈对程序员更明显)。 但是在大多数情况下,可以在C ++中调用未定义的行为。

在调用f2之前x不会被解构吗?

是的。 这意味着return x评估一个悬空引用,该引用引用了未定义的行为。

在这种情况下,您可能更喜欢按值捕获。

f2 = [x]() { return x; }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM