【问题标题】:What is the lifetime of a default argument temporary bound to a reference parameter?临时绑定到引用参数的默认参数的生命周期是多少?
【发布时间】:2012-09-15 07:09:25
【问题描述】:

我认为引用只是将临时对象的生命周期延长到引用本身的生命周期,但以下 sn-p 的输出似乎是矛盾的:

#include <iostream>

struct X{ ~X(){ std::cout << "Goodbye, cruel world!\n"; } };

X const& f(X const& x = X()){
  std::cout << "Inside f()\n";
  return x;
}

void g(X const& x){
  std::cout << "Inside g()\n";
}

int main(){
  g(f());
}

Live example. 输出:

Inside f()
Inside g()
Goodbye, cruel world!

所以似乎在调用g() 之后临时被销毁了......什么给出了?

【问题讨论】:

    标签: c++ language-lawyer lifetime temporary-objects


    【解决方案1】:

    标准在§12.2 [class.temporary] 的特殊情况下处理这个问题:

    p4 在两种情况下,临时对象在与完整表达式结尾不同的点被销毁。 [...]

    p5 第二个上下文是引用绑定到临时的。引用绑定到的临时对象或作为引用绑定到的子对象的完整对象的临时对象在引用的生命周期内持续存在,除了:

    • 临时绑定到函数调用 (5.2.2) 中的引用参数一直存在,直到包含调用的完整表达式完成

    该标准还对完整表达式及其子表达式的评估与§1.9 [intro.execution] p11 中的默认参数有一个方便的说明:

    [ 注意:完整表达式的求值可以包括在词法上不属于完整表达式的子表达式的求值。例如,评估默认参数(8.3.6)所涉及的子表达式被认为是在调用函数的表达式中创建的,而不是定义默认参数的表达式。 ——尾注 ]

    【讨论】:

      【解决方案2】:

      有趣,+1。 (我并不是要在这里与您的好自我回答竞争)。对任何感兴趣的人来说只是一个旁注。如果您想要类似的效果但允许非常量,您可以使用移动语义:

      #include <iostream>
      
      struct X{
         ~X(){ std::cout << "Goodbye, cruel world!\n"; }
         X(X && x){  std::cout << "moved "; }
         X(){}
      };
      
      X  f(X x = X()){
        std::cout << "Inside f()\n";
        return x;
      }
      
      void g(X x){
        std::cout << "Inside g()\n";
      }
      
      int main(){
         g(f());
      }
      

      给了

      Inside f()
      moved Inside g()
      Goodbye, cruel world!
      Goodbye, cruel world!
      

      【讨论】:

      【解决方案3】:

      所以看起来临时在 g() 被调用后被销毁了。

      这是真的,因为临时的生命周期在 f() 被调用后开始,在 g() 退出后结束。那是因为:

      在函数调用 (5.2.2) 中对引用参数的临时绑定一直存在,直到包含调用的 full-expression 完成。

      这里的完整表达式g(f())而不是f(),因为你的f()函数实际上是这样的

      void g(X const& x){
        std::cout << "Inside g()\n";
      }
      
      X const& f(X const& x){
        std::cout << "Inside f()\n";
        return x;
      }
      
      g(f( X() ));
      

      【讨论】:

        猜你喜欢
        • 2021-11-03
        • 2021-12-24
        • 2012-04-28
        • 2021-06-28
        • 1970-01-01
        • 2019-10-09
        • 2010-09-14
        • 1970-01-01
        • 2021-07-21
        相关资源
        最近更新 更多