我正在观看CppCon 2015视频:为什么按价值捕捉是好的,而参考则是坏的。
亚瑟解释说,但是我没有得到它......亚瑟说一个错误的引用是指一个局部变量然后退出,但退出堆栈后应该清理并且局部变量消失了,那么问题是什么? / p>答案 0 :(得分:6)
BAD_increment_by
返回一个闭包,其中包含对y
的引用,但y
在该函数返回时超出范围,因此它包含一个悬空引用。任何调用该闭包的尝试都是未定义的行为。
由于同样的原因,这很糟糕:
int& BAD_copy(int x) { return x; }
很糟糕。
答案 1 :(得分:3)
我想尝试解释@ Barry的答案以另一种方式说的话。
让我们写下BAD_increment_by
内发生的事情。
y
。y
。这会创建一个名为y
的引用。好吧,它们碰巧有相同的名字,令人困惑......让我们称第一个为“值y
”,第二个为“引用y
”。y
。BAD_increment_by
返回。从BAD_increment_by
返回后,
y
已不复存在。y
仍然指向值y
... y
不存在!参考y
指向不存在的东西!当有人调用lambda时,
y
。y
是引用,我们会重定向到值y
。y
还是仅仅是我的幻觉?结论是:当调用lambda时,使用悬空引用。行为未定义。
答案 2 :(得分:1)
您可以将lambda视为已定义operator()
的类的简写,因此可以将其视为函数。
auto BAD_increment_by(int y)
{
return [&](int x){return x+y;};
}
可以考虑以下方面的简写:
struct BadClosure
{
int& y;
BadClosure(int& y) // y is the only variable in scope
: y(y) // So the `&` only captures 'y'
{}
auto operator()(int x){return x+y;}
};
auto BAD_increment_by(int y)
{
return BadClosure(y);
}
所以,如果我使用上述内容:
int main()
{
// This object now has a reference to
// parameter 'y' from the function `BAD_increment_by()`
//
// But this function has exited.
// So the reference held by this object is no longer
// valid (ie it is a dangling reference).
auto addTwo = BAD_increment_by(2);
// Now use it
// Internally this access the member y
// which is a reference to the parameter 'y'
// from a function that is no longer executing.
std::cout << addTwo(5) << "\n";
}