#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()
后来。
就像使用悬空指针一样,这是未定义的行为。同样,编译器会让你 "使用 "这样的指针,但作为程序员,你有责任知道你正在违反规则。