【问题标题】:C++ extending lifetime of &&C++ 延长 && 的生命周期
【发布时间】:2016-05-29 21:23:53
【问题描述】:

在以下示例中:

http://coliru.stacked-crooked.com/a/7a1df22bb73f6030

struct D{
    int i;    
    auto test2(int&& j){
        return [&](){       // captured by reference!
            cout << i*(j);
        };
    }    
};

int main()
{
    D d{10};
    {
      auto fn = d.test2(10);
      fn();                     // 1. wrong result here

      d.test2(10)();            // 2. but ok here
    }
}

为什么d.test2(10)(); 有效?

它真的应该起作用吗,或者那只是我未定义的行为等于正确的结果?

P.S. 阅读this 后,我只看到一种解释:在(2)中,临时生命周期延长到表达式结束,并且调用发生在与 && crteation; 相同的表达式中;而 (1) 实际上由 2 个表达式组成:

在函数调用中存在临时绑定到引用参数 直到包含该函数调用的完整表达式的结尾: if 该函数返回一个引用,该引用比完整表达式的寿命长, 它变成了一个悬空引用。

是这样吗?

【问题讨论】:

  • 是的,您找到并输入问题的答案是正确答案。
  • @hvd - 你确定吗?我实际上找不到“表达”的定义。
  • 是的,非常确定。 “表达式”是语法中的产生式。 “全表达式”在[intro.execution]p10中定义,基本意思是“不是子表达式的表达式”,意思是d.test2(10)();语句中唯一的全表达式是d.test2(10)()
  • @hwd - 所以...“表达式”可以被“;”识别还是序列点?我的意思是我可以用d.test2(10)(); 之类的行来意外地将表达式分成两个(因此得到悬空引用)吗?
  • @AnT 是的 - 你是对的,const int&amp; 我得到了同样的行为

标签: c++ c++11 rvalue-reference temporary


【解决方案1】:

一个临时对象会一直持续到它被创建的(嗯,完整的表达式)的末尾,除非生命周期被延长。

您的代码不会延长任何临时对象的生命周期。通过绑定到引用的生命周期延长不会“交换”,只有第一个绑定延长生命周期。

因此,最简单的情况是 UB,因为您有一个悬空的参考。被引用的临时对象在行尾消失:在下一行你跟随引用,混乱发生了。

在第二种情况下,您的引用不会延长临时的生命周期,但临时的持续时间比绑定到它的引用长!他们都死在行的末端,以相反的构造顺序。

所以调用有效。

【讨论】:

  • by line 你的意思是 full-expression - 当然可以在一行中有多个语句
  • @M.M 是的,有人可以将一堆; 分隔的完整表达式串在一起。 :) 一个完整的表达式可以跨越多行。
  • @Yakk:您知道标准中为什么“通过绑定到引用延长生命周期不会'通勤'”的参考吗?或者也许更好,一个启发式的解释来帮助记住和解释为什么会这样?
  • @chris 引用在某些情况下会延长临时引用的生命周期。没有任何子句会导致一个引用绑定到另一个引用以进一步扩展它。绑定到构造函数中的引用的临时对象有一个例外,但这会缩短生命周期而不是进一步扩展它。不知道如何引用缺席!也许有注释。规则的英文版本是:直接绑定到引用的临时对象的生命周期延长到引用生命周期,除非在 ctor 初始化器列表中。否则,临时人员会在;(大致)离开
【解决方案2】:

它真的应该起作用吗,或者那只是我未定义的行为等于正确的结果?

好像是这样。在您链接的示例中,您会收到以下警告:

warning: '<anonymous>' is used uninitialized in this function [-Wuninitialized]

未初始化的对象具有不确定的值,尝试访问这些值会导致未定义的行为。

【讨论】:

  • 只有某些版本的 gcc 会抛出它。 clang 根本不会产生任何警告。
  • 抱歉,您误读了警告。如果您注释掉 OP 已经指出不工作的调用,您会发现 GCC 没有发出任何警告,而且不发出警告是正确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-03
  • 2020-09-17
  • 1970-01-01
  • 2015-07-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多