如果我通过引用捕获一个局部变量,而它超出了作用域,会发生什么?

19

假设我使用lambda作为回调函数,并在创建lambda时通过引用捕获本地函数变量。现在假设lambda对象直到该本地函数变量超出范围后才执行。会发生什么?

我意识到如果存在这种可能性,有人这样做将非常愚蠢,但我几乎肯定会有人这样做。


我不熟悉C++11,但对于我使用过的其他任何语言来说,通过定义捕获变量意味着只要被捕获(存在任何[间接]引用),它就不会超出作用域。 - 500 - Internal Server Error
8
不适用于 C++。返回一个通过引用捕获局部变量的 lambda 表达式,意味着一旦封闭函数返回,该引用将不再有效。这将导致未定义的行为。 - Frédéric Hamidi
函数本身是静态的,因此始终有效。但 void (**)() 可能会成为悬空指针。还有什么别的? - Joop Eggen
@Joop,我认为提问者将一个函数指针存储到一个局部变量中并捕获了该变量。即使函数指针仍然有效,对局部变量的引用也不会有效。 - Frédéric Hamidi
2
@RepDbg,在C++11中不会发生lifting,悬空引用会导致未定义的行为。请参见https://dev59.com/jFnUa4cB1Zd3GeqPanZI。 - Frédéric Hamidi
最近我遇到了这个问题,但我的编译器(VC2019)没有给我任何警告,如果有警告的话,会节省一些工作。在VC或gcc/clang中是否有警告可以告诉我这个问题? - cmaughan
2个回答

16

是的,那将会引发悬垂引用问题。你似乎对接口设计感到担忧:"我几乎可以肯定有人会这么做。" 请不要因为这个理由而拒绝使用Lambda和std::function,它们并没有比其他选择更危险。Lambda只是更简单的定义本地Functor的一种方式。std::function是持久、多态Functor的最佳接口,无论Lambda是否存在。

作用域问题是为什么通过值捕获更容易。用户除非写&,否则不会得到一个引用。当然,危险在于有些人会养成以[&]开始他们所有的lambda函数的习惯,因为引用“更快”。希望这样的人很快就能吸取教训…尽管有些指针狂热者是无可救药的。


12

当你返回一个局部变量的引用时,发生的事情与此相同:未定义行为。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接