C++ 如果通过lambda函数对象返回对局部变量的引用,会发生什么? #包括 自动获取_lambda() { int i=5; 自动lambda=[&i](){std::cout

C++ 如果通过lambda函数对象返回对局部变量的引用,会发生什么? #包括 自动获取_lambda() { int i=5; 自动lambda=[&i](){std::cout,c++,c++11,lambda,reference,C++,C++11,Lambda,Reference,i仅在其作用域内可用,该作用域位于get_lambda()内。显然,它在其作用域外不可用,这是稍后调用lambda()时尝试的 就像使用悬空指针一样,这是未定义的行为。类似地,编译器将允许您“使用”这样的指针,但作为程序员,您有责任知道您正在违反规则。i仅在其作用域中可用,该作用域位于get\u lambda()内。显然,它在其作用域之外是不可用的,这是您稍后调用lambda()时尝试的 就像使用悬空指针一样,这是未定义的行为。类似地,编译器将允许您“使用”这样的指针,但作为程序员,您有责任知道

i
仅在其作用域内可用,该作用域位于
get_lambda()
内。显然,它在其作用域外不可用,这是稍后调用
lambda()
时尝试的


就像使用悬空指针一样,这是未定义的行为。类似地,编译器将允许您“使用”这样的指针,但作为程序员,您有责任知道您正在违反规则。

i
仅在其作用域中可用,该作用域位于
get\u lambda()内
。显然,它在其作用域之外是不可用的,这是您稍后调用
lambda()
时尝试的


就像使用悬空指针一样,这是未定义的行为。类似地,编译器将允许您“使用”这样的指针,但作为程序员,您有责任知道您正在违反规则。

在您的情况下,您正在调用。
i
名称是
get\u lambda()的本地名称
函数,一旦
i
超出作用域,它就会被销毁。因此,使用lambda,您现在存储的是对不再存在的对象的引用。这也称为悬挂引用。请改为按值捕获局部变量:

#include <iostream>

auto get_lambda()
{
    int i = 5;
    auto lambda = [&i]() { std::cout << i << '\n'; };
    return lambda;
}

int main()
{
    auto lambda = get_lambda();
    lambda();
}

auto lambda=[i](){std::cout在您的例子中,您正在调用
函数,一旦
i
超出作用域,它就会被销毁。因此,使用lambda,您现在存储的是对不再存在的对象的引用。这也称为悬挂引用。请改为按值捕获局部变量:

#include <iostream>

auto get_lambda()
{
    int i = 5;
    auto lambda = [&i]() { std::cout << i << '\n'; };
    return lambda;
}

int main()
{
    auto lambda = get_lambda();
    lambda();
}

自动lambda=[i](){std::cout在lambda函数体中,可以将
i
设置为任何值并读取它。因此它是可用的,但正如您所说,我认为它是一个悬空指针。我认为
i
位于堆栈指针下方,因此被其他函数使用,这些函数后来在
main
中调用。我不明白你的意思是“在lambda函数体中,可以将i设置为任何值并读取它。因此它是可用的”。在那里,唯一可用的方法是调用
lambda()
Inside
get\u lambda()
,否则它会爆炸,因为
i
不再存在。如果我替换这个
{std::cout Right,仍然是未定义的行为,如“允许发生任何事情”。当数据损坏时,这一点非常重要,“如果你非常不走运,该程序将完全按照你希望的那样运行,直到你更改了一些不相关的代码/编译器版本/编译器供应商/操作系统/硬件平台–然后一个新的bug出现,你不知道为什么看似正确的代码现在无法正常工作"。这很好。在lambda函数体中,可以将
i
设置为任何值并读取它。因此它是可用的,但正如您所说,我认为它是一个悬空指针。我认为
i
位于堆栈指针下方,因此被其他函数使用,这些函数后来在
main
中调用。我不理解你所说的“在lambda函数体内部,可以将i设置为任何值并读取它。因此它是可用的”。唯一可用的方法是,如果你调用
lambda()
Inside
get\u lambda()
,否则它会爆炸,因为
i
不再存在。如果我替换这个
{std::cout Right,仍然是未定义的行为,如“允许发生任何事情”。当数据损坏时,这一点非常重要,“如果你非常不走运,该程序将完全按照你希望的那样运行,直到你更改了一些不相关的代码/编译器版本/编译器供应商/操作系统/硬件平台–然后一个新的bug出现,你不知道为什么看似正确的代码现在无法正常工作"。看到这个很好。我知道通过值捕获可以避免这个问题。我从C中知道,在一个函数中,指向已经返回的局部变量的指针是一个悬空指针。但我很惊讶,这在引用中也是可能的。我知道悬空指针,但悬空引用对我来说是新的。@PaulSanders这是一个implementation细节。编译器在内部使用指针实现引用是很常见的,但这不是标准所要求的,而且并非所有的实现都会这样做。我知道通过值捕获可以避免这个问题。我从C中知道,在函数中,指向已返回的局部变量的指针是一个悬念g指针。但我很惊讶引用也能实现这一点。我知道悬挂指针,但悬挂引用对我来说是新的。@PaulSanders这是一个实现细节。编译器在内部使用指针实现引用是很常见的,但这不是标准所要求的,而且并非所有实现都这样做.
auto lambda = [=]() { std::cout << i << '\n'; };