C++ 什么时候捕获变量?

C++ 什么时候捕获变量?,c++,c++11,lambda,std-function,C++,C++11,Lambda,Std Function,我正在做一个回调函数的std::vector,我在理解捕获方面有点困难。如果我通过引用进行捕获,当我尝试使用它们时,它们似乎超出了范围。如果我用价值来衡量,一切都是有效的 使用这些回调函数的代码需要特定的签名,因此假设我无法修改使用这些回调函数的代码,我需要使用捕获变量,而不是将其作为函数参数传递 何时捕获localVar?是在定义lambda时,还是在调用lambda时?答案是否会根据我是通过值还是引用捕获而变化 下面是一个我想了解的小例子: #include <iostream>

我正在做一个回调函数的
std::vector
,我在理解捕获方面有点困难。如果我通过引用进行捕获,当我尝试使用它们时,它们似乎超出了范围。如果我用价值来衡量,一切都是有效的

使用这些回调函数的代码需要特定的签名,因此假设我无法修改使用这些回调函数的代码,我需要使用捕获变量,而不是将其作为函数参数传递

何时捕获
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;
}
#包括
#包括
#包括
int main(int argc,字符**argv)
{
int n(5);
//生成lambda函数的向量
std::向量fs;
对于(尺寸i=0;iint//将&localVar更改为localVar,它就可以工作了
{
返回localVar+100;
};
fs.向后推(我的lambda);
}
//使用lambda函数的向量
对于(尺寸i=0;i
在本例中,
auto my_lambda=[&localVar]()->int
创建一个lambda,其中引用了本地变量
localVar

std::cout创建lambda时捕获引用。从未捕获引用对象的值。调用lambda时,无论何时使用它(与使用任何其他引用一样),它都将使用引用来确定引用对象的值。如果在引用对象停止存在后使用引用,则使用的是悬挂引用,这是未定义的行为

在本例中,
auto my_lambda=[&localVar]()->int
创建一个lambda,其中引用了本地变量
localVar

std::cout
如果我通过引用进行捕获,当我尝试使用它们时,它们似乎超出了范围

没错。您创建了一个lambda,它封装了对局部变量的引用。该变量超出了作用域,使该引用悬空。这与任何其他引用都没有区别

捕获“发生”在您定义lambda的地方——这就是它的目的!如果它发生在以后,当您调用lambda(什么时候?)时,您想要捕获的东西将早就消失了,或者至少是无法实现的

捕获允许我们“保存”现在可以命名的东西,以备将来使用。但是如果您通过引用捕获,最好在使用该引用时确保引用的东西仍然存在

不过,要注意像这样的古怪行为

如果我通过引用进行捕获,当我尝试使用它们时,它们似乎超出了范围

没错。您创建了一个lambda,它封装了对局部变量的引用。该变量超出了作用域,使该引用悬空。这与任何其他引用都没有区别

捕获“发生”在您定义lambda的地方——这就是它的目的!如果它发生在以后,当您调用lambda(什么时候?)时,您想要捕获的东西将早就消失了,或者至少是无法实现的

捕获允许我们“保存”现在可以命名的东西,以备将来使用。但是如果您通过引用捕获,最好在使用该引用时确保引用的东西仍然存在


但是要注意一些奇怪的事情,比如。

auto my_lambda=[&localVar]()->int
捕获对
localVar
的引用。然后执行
push_back
,然后
localVar
消失,如果调用lambda,则具有未定义的行为。假设
fs
是一个
std::vector
并且在循环中执行了
fs.push_back(&localVar)
。退出定义了
localVar
的块后,您是否希望存储的指针有效?您可以将lambda视为具有重载
运算符()的类的实例
。如果通过引用捕获,就像拥有类的引用成员一样;您必须注意,当lambda的实例仍在被调用时,所引用的对象不会停止存在于
auto my_lambda=[&localVar]()->int
捕获对
localVar
的引用。然后执行
push_back
,然后
localVar
消失,如果调用lambda,则具有未定义的行为。假设
fs
是一个
std::vector
并且在循环中执行了
fs.push_back(&localVar)
。退出定义了
localVar
的块后,您是否希望存储的指针有效?您可以将lambda视为具有重载
运算符()的类的实例
。如果通过引用捕获,就像拥有类的引用成员一样;您必须注意,当lambda实例仍在被调用时,被引用的对象不会停止存在