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