void foo(const Object & o = Object()) {
return;
}
在上面的函数中,什么时候应该调用 ~Object ?当函数退出或在调用站点周围的块结束时?
void foo(const Object & o = Object()) {
return;
}
在上面的函数中,什么时候应该调用 ~Object ?当函数退出或在调用站点周围的块结束时?
默认参数将在包含函数调用的完整表达式的末尾被销毁。
为了详细说明大卫所说的,标准在第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();
编辑:正如迈克尔在他的评论中指出的那样,我给出的这个“语句/分号”类比是对“完整表达”一词的简化,在某些情况下它有点不同,比如他的例子:
if(foo()) bar();
调用之前会破坏临时bar
的,因此与表达式语句不同:
foo() ? bar() : 0;
但是尽管如此,“分号”类比通常是一个很好的选择,即使完整表达式不一定与语句相同(可以由多个完整表达式组成)。
我认为这段代码不应该编译。您不能将引用绑定到临时文件,除非它是const
. 如果它是const
临时的,则应保持活动状态,直到函数表达式结束。与在其中定义的局部变量相同。