【问题标题】:when are default argument object destroyed?默认参数对象何时被销毁?
【发布时间】:2012-12-27 21:25:36
【问题描述】:
void foo(const Object & o = Object()) {
      return;
}

在上面的函数中,~Object 应该什么时候被调用?当函数退出或在调用站点周围的块结束时?

【问题讨论】:

  • 我相信默认参数是作为函数调用表达式的一部分构造的。
  • @JesseGood Object 的隐含定义应该是,AFAIK。
  • clang++ 说“example.cpp:7:19: 错误:对‘Object’类型的非常量左值引用不能绑定到‘Object’类型的临时对象”。
  • @LuchianGrigore:是的,代码已更新为const

标签: c++ destructor


【解决方案1】:

默认参数将在包含函数调用的完整表达式的末尾被销毁。

【讨论】:

  • 我不确定您所说的“在完整表达式的末尾”是什么意思。这是否意味着析构函数可以在范围边界以外的其他地方调用?
  • @GreyGeek 当临时对象绑定到引用时,对象的生命周期变为引用的生命周期。所以在这种情况下,它会在函数返回时被销毁。
  • @SethCarnegie 这是有道理的,但这与大卫的答案相反......
  • @SethCarnegie 这并不完全正确,它一直持续到包含调用的语句结束,就像 David 所说并在我的回答中进一步解释。
  • @GreyGeek:考虑:g(f());,对f() 的调用在g() 之前排序,因此它必须在调用g() 之前完成。另一方面,为f() 提供默认参数而创建的临时变量将一直存在,直到g() 返回后整个表达式完成。
【解决方案2】:

为了详细说明 David 所说的内容,该标准在 12.2 [class.temporary] 节中说:

临时对象在两种情况下被销毁 与完整表达式的结尾不同的点。 [...] 第二 上下文是引用绑定到临时对象的时间。临时到 引用是绑定的还是完整的临时的 引用绑定到的子对象的对象持续存在 引用的生命周期,除了:

  • ...
  • 在函数调用 (5.2.2) 中临时绑定到引用参数会一直持续到完整表达式完成为止 包含调用。
  • ...

因此它们既不会在函数退出时也不会在包含调用的块结束时被销毁,而是在包含函数调用的完整语句的末尾(简单地说,在函数调用后的第一个分号处,在调用上下文)。

编辑:所以说我们得到了:

int foo(const Object & o = Object());

some_stuff();    
std::cout << (foo() + 7);
other_stuff();

这大致相当于以下内容(注意概念范围块):

some_stuff(); 
{
    Object o;             // create temprorary
    int i = foo(o);       // and use it
    int j = i + 7;        // do other things
    std::cout << j;       // while o still alive
}                         // finally destroy o
other_stuff();

编辑:正如 Michael 在他的评论中指出的那样,我给出的这个 “语句/分号” 类比是对"full-expression" 这个词在某些情况下有点不同,比如他的例子:

if(foo()) bar();

这会在调用bar 之前破坏临时变量,因此与表达式语句不同:

foo() ? bar() : 0;

但是,“分号” 类比通常很合适,即使完整表达式不一定与语句相同(可以由多个完整表达式组成)。

【讨论】:

  • 吹毛求疵:它会在完整表达式的末尾被销毁,这不一定与语句相同。例如,假设foo() 返回一个int,那么在if (foo()) bar(); 中,作为foo() 的默认参数创建的对象将在调用bar()(或if 语句之后的任何内容)之前被销毁。因此,表达式语句 foo() ? bar() : 0; 与语句 if (foo()) bar(); 的语义略有不同,因为调用 Object() dtor 的时间不同。
  • @MichaelBurr 确实,但使用 "semicolon" 类比经常使用,我想简化不那么明显的 "full-expression"-短语。但你举了一个很好的例子。
【解决方案3】:

我认为这段代码不应该编译。除非它是 const,否则不能将引用绑定到临时对象。如果它是const,则临时应保持活动状态,直到函数表达式结束。与在其中定义的局部变量相同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多