C++ 默认参数对象何时被销毁?
在上面的函数中,应该何时调用~Object?当函数退出或位于调用站点周围的块末尾时?默认参数将在包含函数调用的完整表达式末尾被销毁。我认为不应编译此代码。不能将引用绑定到临时对象,除非它是C++ 默认参数对象何时被销毁?,c++,destructor,C++,Destructor,在上面的函数中,应该何时调用~Object?当函数退出或位于调用站点周围的块末尾时?默认参数将在包含函数调用的完整表达式末尾被销毁。我认为不应编译此代码。不能将引用绑定到临时对象,除非它是const。如果它是const,则临时变量应保持活动状态,直到函数表达式结束。与其中定义的局部变量相同。为了详细说明David所说的内容,标准在第12.2节[class.temporary]中规定: 有两种情况下,临时机构会在同一时间被销毁 与完整表达式的结尾不同的点。[……]第二 上下文是指引用绑定到临时对象
const
。如果它是const
,则临时变量应保持活动状态,直到函数表达式结束。与其中定义的局部变量相同。为了详细说明David所说的内容,标准在第12.2节[class.temporary]中规定:
有两种情况下,临时机构会在同一时间被销毁
与完整表达式的结尾不同的点。[……]第二
上下文是指引用绑定到临时对象的时间。临时立法会
哪个引用是绑定的,哪个临时引用是完整的
将引用绑定到的子对象的对象对于
引用的有效期,但以下情况除外:
- 在函数调用(5.2.2)中临时绑定到引用参数的情况会一直持续到完整表达式完成 包含呼叫
void foo(const Object & o = Object()) {
return;
}
这将在调用条之前销毁临时语句,因此与表达式语句不同:
if(foo()) bar();
但是,即使一个完整表达式不一定与一个语句(可以由多个完整表达式组成)相同,但“分号”类比通常是一个很好的选择。我相信默认参数是作为函数调用表达式的一部分构造的。@JesseGood使用对象的隐含定义
它应该,AFAIK.clang++说“example.cpp:7:19:错误:对“Object”类型的非常量左值引用无法绑定到“Object”类型的临时引用。@LuchianGrigore:是的,代码更新为const
。我不确定您所说的“在完整表达式的末尾”是什么意思。这是否意味着可以在范围边界以外的其他地方调用析构函数?@GreyGeek当临时对象绑定到引用时,该对象的生存期将变为引用的生存期。因此,在本例中,当函数返回时,它将被销毁。@SethCarnegie这是有意义的,但它与david回答的相反…@SethCarnegie这不是完全正确的,它会一直存在到包含调用的语句结束,正如david所说,并在我的回答中作了进一步解释。@GreyGeek:考虑:g(f())
,对f()
的调用在g()
之前排序,因此必须在调用g()
之前完成。另一方面,为提供f()
的默认参数而创建的临时变量将一直存在,直到g()
返回后整个表达式完成。挑剔:它将在完整表达式结束时销毁,这不一定与语句相同。例如,假设foo()
返回一个int,然后在if(foo())bar()中
创建为foo()
默认参数的对象将在调用bar()
(或if
语句后面的任何内容)之前销毁。那么表达式语句foo()?bar():0
的语义与if(foo())bar()语句的语义稍有不同代码>由于调用对象()
dtor的时间不同。@MichaelBurr确实如此,但通过经常使用的“分号”类比,我想简化不太明显的“完整表达式”短语。但你举了一个很好的例子。
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();
foo() ? bar() : 0;