#include <iostream>
auto get_lambda()
{
int i = 5;
auto lambda = [&i]() { std::cout << i << 'n'; };
return lambda;
}
int main()
{
auto lambda = get_lambda();
lambda();
}
在"get_lambda"函数中,我定义了局部变量"I"。然后,该函数返回lambda对象,该对象具有对该局部变量的一个捕获引用。在"main"内部,我调用那个lambda,结果"I"是未初始化的内存。
变量"i"位于get_lambda的堆栈上。当函数返回时,此堆栈不再有效。
为什么这段代码要编译,变量"i"到底发生了什么,它在get_lambda之外仍然可用吗?
在您的案例中,您正在调用未定义的行为。i
名称是get_lambda()
函数的本地名称,一旦i
超出作用域,它就会被销毁。因此,使用lambda,您现在存储的是对已经不存在的东西的引用。这也被称为悬挂引用。按值捕获本地变量:
auto lambda = [i]() { std::cout << i << 'n'; };
或:
auto lambda = [=]() { std::cout << i << 'n'; };
实际上,您可以通过lambda的捕获列表中的引用来捕获本地变量。因此,没有编译器错误。根据编译器的不同,可能会发出警告。
i
仅在其作用域中可用,该作用域位于get_lambda()
内部。显然,它在其作用域之外是不可用的,这正是您稍后调用lambda()
时所尝试的。
就像使用悬挂指针一样,这是未定义的行为。同样,编译器会让你"使用"这样一个指针,但作为程序员,你有责任知道你违反了规则。