C ++ lambda:良好的参考与糟糕的参考

时间:2016-05-03 03:52:59

标签: c++ lambda reference pass-by-reference

我正在观看CppCon 2015视频:为什么按价值捕捉是好的,而参考则是坏的。

Enter image description here

亚瑟解释说,但是我没有得到它......亚瑟说一个错误的引用是指一个局部变量然后退出,但退出堆栈后应该清理并且局部变量消失了,那么问题是什么? / p>

3 个答案:

答案 0 :(得分:6)

BAD_increment_by返回一个闭包,其中包含对y的引用,但y在该函数返回时超出范围,因此它包含一个悬空引用。任何调用该闭包的尝试都是未定义的行为。

由于同样的原因,这很糟糕:

int& BAD_copy(int x) { return x; }

很糟糕。

答案 1 :(得分:3)

我想尝试解释@ Barry的答案以另一种方式说的话。

让我们写下BAD_increment_by内发生的事情。

  1. 有一个局部变量y
  2. 通过引用获取lambda y。这会创建一个名为y的引用。好吧,它们碰巧有相同的名字,令人困惑......让我们称第一个为“值y”,第二个为“引用y”。
  3. lambda的主体使用引用y
  4. lambda由BAD_increment_by返回。
  5. BAD_increment_by返回后,

    1. 价值y已不复存在。
    2. 参考y仍然指向值y ...
    3. 等待!值y不存在!参考y指向不存在的东西!
    4. 当有人调用lambda时,

      1. 读取参考y
      2. 由于引用y是引用,我们会重定向到值y
      3. Errr ......它真的值y还是仅仅是我的幻觉?
      4. 结论是:当调用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";
}