如果你通过lambda函数对象返回一个对局部变量的引用会发生什么?

问题描述 投票:0回答:1
#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之外还能使用吗?

c++ c++11 lambda reference
1个回答
2
投票

在你的例子中,你调用了 未定义的行为. 该 i 名字是本地的 get_lambda() 功能,一旦 i 出了范围,它就会被销毁。所以,在你的lambda中,你现在存储了一个已经不存在的东西的引用。这也就是所谓的 悬指. 用值来代替捕捉局部变量。

auto lambda = [i]() { std::cout << i << '\n'; };

或者:

auto lambda = [=]() { std::cout << i << '\n'; };

你确实可以在lambda的捕获列表中通过引用来捕获局部变量。因此,不会出现编译器错误。根据编译器的不同,可能会发出一个警告。


2
投票

i 仅在其作用域中可用,也就是在 get_lambda(). 很明显,在它的范围之外,它是不能使用的,这就是你在调用 lambda() 后来。

就像使用悬空指针一样,这是未定义的行为。同样,编译器会让你 "使用 "这样的指针,但作为程序员,你有责任知道你正在违反规则。

© www.soinside.com 2019 - 2024. All rights reserved.