何时捕获捕获变量?

Tay*_*lor 1 c++ lambda c++11 std-function

我正在进行std::vector回调std::function,而我在理解捕获时遇到了一些麻烦.当我尝试使用它们时,它们似乎超出了范围,如果我通过引用捕获它们.如果我按价值捕获,一切正常.

使用这些回调函数的代码需要一定的签名,所以假设我无法修改使用它们的代码,我需要坚持使用捕获变量而不是将事物作为函数参数传递.

localVar捕获?是在定义lambda还是调用lambda时?答案是否会根据我是按值还是参考来捕获?

这是我想要了解的一个小例子:

#include <iostream>
#include <functional>
#include <vector>

int main(int argc, char **argv)
{

    int n(5);

    // make a vector of lambda functions
    std::vector<std::function<const int(void)> > fs;
    for(size_t i = 0; i < n; ++i){
        int localVar = i;
        auto my_lambda = [&localVar]()->int // change &localVar to localVar and it works
        {
            return localVar+100;
        };
        fs.push_back(my_lambda);
    }

    // use the vector of lambda functions
    for(size_t i = 0; i < n; ++i){
        std::cout << fs[i]() << "\n";
    }


    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Fra*_*eux 8

参考在创建拉姆达被捕获.永远不会捕获引用对象的.当你调用lambda时,它会使用引用来确定引用对象的值(就像使用任何其他引用一样).如果在引用的对象不再存在后使用引用,则使用的是悬空引用,它是未定义的行为.

在这种情况下,auto my_lambda = [&localVar]()->int创建一个lambda,其中包含一个名为localVarlocal变量的引用localVar.

std::cout << fs[i]() << "\n";叫一个lambdas.但是,当lambda执行时return localVar+100;,它会尝试使用对localVar局部变量的引用localVar(第一个for循环的本地变量),但该局部变量不再存在.你有未定义的行为.

如果删除&符号并使用localVarvalue(auto my_lambda = [localVar]()->int),则会在创建lambda时捕获值的副本.因为它是副本,所以原始版本发生了什么并不重要localVar.

你可以在http://en.cppreference.com/w/cpp/language/lambda#Lambda_capture上看到这个.