C++ Lambda变量捕获

C++ Lambda变量捕获,c++,lambda,c++11,C++,Lambda,C++11,我对lambda表达式的变量捕获部分的性质感到困惑 void f1(); std::function<int()> f2; int main() { f1(); std::cout<<f2()<<endl; } void f1() { int x; f2 = [&]() { return x; }; } void f1(); std::功能f2; int main(){ f1(); 标准::

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

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

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

void f1() {
    int x;
    f2 = [&]() {
        return x;
    };
}
void f1();
std::功能f2;
int main(){
f1();
标准::cout
在调用f2之前x不是被解构了吗

是的,它是。这意味着
返回x
计算悬空引用,该引用调用未定义的行为

在本例中,您可能更喜欢按值捕获

f2 = [x]() { return x; }
在调用f2之前x不是被解构了吗

是的,它是。这意味着
返回x
计算悬空引用,该引用调用未定义的行为

在本例中,您可能更喜欢按值捕获

f2 = [x]() { return 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;
    };
}
(对于int,没有什么理由不按值存储它:对于更复杂的类型,您可能希望避免不必要地复制它)

注意,上面的评论以一种更有趣的方式解释了这一点


现在,当你减少堆栈的数量以捕捉这种未定义的行为时,一些编译器会用特殊的值来标记堆栈(顺便捕捉,我的意思是让它对程序员来说更明显)但在大多数情况下,调用C++中的未定义行为是可能的。

< P>是的。您已经成功调用了未定义的行为。一个可能的结果是获得X的值。另一种是计算机格式化硬盘驱动器,程序崩溃,或者计算机转换成机器人面包师刺客,为您提供纸杯蛋糕,M。我以为你得了腹腔疾病

这方面的一个安全变体可能是:

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

void f1(int x) {
    std::shared_ptr<int> spX( new int(x) );
    f2 = [=]() {
        return *spX;
    };
}
(对于int,没有什么理由不按值存储它:对于更复杂的类型,您可能希望避免不必要地复制它)

注意,上面的评论以一种更有趣的方式解释了这一点


现在,当你减少堆栈的数量以捕捉这种未定义的行为时,一些编译器会用特殊的值来标记堆栈(顺便捕捉,我的意思是让它对程序员来说更明显)但是,在大多数情况下,调用C++中的未定义行为是可能的。

我认为这是UB!请阅读。如果把lambda传递到线程中,情况会变得更糟( ASYNC/<代码>)。我认为这是UB!请阅读。如果将lambda传递到线程( ASYNC/<代码>),情况会变得更糟。。它只是
[x]
[=]
用于按值自动捕获未命名的外部项。它只是
[x]
[=]
用于按值自动捕获未命名的外部项。