何时销毁默认参数对象?

Gre*_*eek 6 c++ destructor

void foo(const Object & o = Object()) {
      return;
}
Run Code Online (Sandbox Code Playgroud)

在上面的函数中,什么时候〜应该被调用的对象?当功能退出时或在呼叫站点周围的块末尾?

Dav*_*eas 9

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


Chr*_*ica 6

详细说明大卫所说的内容,标准在第12.2[class.temporary]中说:

有两种情况,临时表在与完整表达结束时不同的地方被摧毁.[...]第二个上下文是指引用绑定到临时.绑定引用的临时对象或绑定引用的子对象的完整对象的临时对象在引用的生命周期内持续存在,除了:

  • ...
  • 函数调用(5.2.2)中的引用参数的临时绑定将持续到包含该调用的完整表达式完成为止.
  • ...

因此,当函数退出时,或者当包含调用的块结束时,它们既不会被破坏,而是在包含函数调用的完整语句的末尾(简单地说,在函数调用之后的第一个分号处,在调用上下文中).

编辑:所以说我们得到:

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

some_stuff();    
std::cout << (foo() + 7);
other_stuff();
Run Code Online (Sandbox Code Playgroud)

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

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();
Run Code Online (Sandbox Code Playgroud)

编辑:正如迈克尔在他的评论中所指出的那样,这个"声明/分号" - 我给出的类似术语是"完整表达"一词的简化,并且有些情况下它有点不同,就像他的例子:

if(foo()) bar();
Run Code Online (Sandbox Code Playgroud)

哪个会在bar调用之前销毁临时文件,因此与表达式语句不同:

foo() ? bar() : 0;
Run Code Online (Sandbox Code Playgroud)

但是,即使完整表达式不一定与语句(可以包含多个完整表达式)相同,"分号" -分类通常也是一个很好的选择.