C ++ lambda值无法捕获

时间:2013-12-24 03:21:00

标签: c++ lambda

这是我的代码,我想在c ++中像javascript一样测试闭包。为什么编译器会产生此消息? “testLambda.cpp:在lambda函数中:     testLambda.cpp:8:11:错误:'a'未被捕获“

    #include <iostream>
    #include <functional>
    std::function<bool(int)> returnLambda(int a){
        auto b  = 1;
        auto c  = 2;

        return [&](int x)
        {   return x*(b++)+c+a == 0;};
    }
    auto f = returnLambda(21);
    int main(){
        auto c = f(1);
        auto b = f(1);

        std::cout<<c<<b<<std::endl;
        return 0;
    }

2 个答案:

答案 0 :(得分:6)

你需要在方括号中指定你的捕获,这就是lambdas首先需要方括号的原因。您可以通过引用捕获它们:

[&a,&b,&c] (int x) ...

或按价值:

[a,b,c] (int x) ...

或混淆:

[a,&b,c] (int x) ...

或者您可以捕获您使用的所有内容:

[&] (int x) ... // by reference
[=] (int x) ... // by value

如果您选择按值捕获变量,但需要修改它,那么您需要使其变为可变:

[=] (int x) mutable ...

答案 1 :(得分:1)

本杰明林德利提供了关于用C ++声明lambda的答案。

但从技术上讲,你无法使用C ++ lambdas重现JavaScript闭包。

在JS中,本地函数使用的外部变量受GC机制保护。

但是在C ++中,如果你通过引用捕获变量,当引用的变量被破坏并且你会得到分段错误/访问冲突时,你可以很容易地进入这种情况。

这个,例如:

#include <iostream>
#include <functional>
std::function<bool(int)> returnLambda(int a){
    auto b  = 1;
    auto c  = 2;

    return [&](int x)
    {   return x*(b++)+c == 0;};
}
auto f = returnLambda(21);
int main(){
    auto c = f(1);
    auto b = f(1);

    std::cout<<c<<b<<std::endl;
    return 0;
}

会在从returnLambda()返回后严重崩溃,当调用函数f()时,它的变量a,b和c被销毁(它们的堆栈位置由其他东西使用)。