函数返回值的自动对象,从而保证被破坏?

在[except.ctor]标准( N4140 )保证:

自从try块被input后,为所有构造的自动对象调用析构函数…

但是在下面的例子中,空输出certificate了函数foo的返回值没有被破坏,尽pipe它已经被构造了。 使用g ++(5.2.1)和clang ++(3.6.2-1)和选项-O0 -fno-elide-constructors -std=c++14

 struct A { ~A() { cout << "~A\n"; } }; struct B { ~B() noexcept(false) { throw 0; } }; A foo() { B b; return {}; } int main() { try { foo(); } catch (...) { } } 

这是g ++和clang ++中的一个bug,还是函数返回值不被视为自动对象,还是C ++语言中的循环漏洞?

没有[stmt.return],[expr.call]或[dcl.fct]我已经能够find一个清晰的语句,函数返回值是否被认为是一个自动对象。 我发现的最接近的提示是6.3.3 p2:

return语句可能涉及到构build和复制或移动临时对象…

和5.2.2 p10:

如果结果types是左值引用types或右值引用,则函数调用是左值,如果结果types是右值引用,则返回值为xvalue,否则为prvalue。

函数返回值被认为是临时的,返回值的构造在当地人被破坏之前被sorting。

不幸的是,这在标准中没有详细说明。 有一个开放的缺陷 ,描述这一点,并提供一些措辞来解决这个问题

[…]具有voidtypes操作数的return语句只能用于返回types为cv void的函数。 任何其他操作数的返回语句只能用于返回types不是cv void的函数; return语句将初始化要从操作数复制初始化(8.5 [dcl.init])返回的对象或引用。 […]

在返回语句的操作数所build立的完整expression式结束时临时对象被破坏之前,对返回实体的复制初始化进行sorting,然后在局部variables(6.6 [stmt。跳转])的封闭返回语句。

由于函数的返回值是临时的,所以它们没有被destructors are invoked for all automatic objects覆盖,在你的文章开始时destructors are invoked for all automatic objects引用destructors are invoked for all automatic objects 。 但是, [class.temporary]/3说:

临时对象被作为评估完整expression式(词法)包含创build点的最后一步被破坏。 即使评估以抛出exception结束,情况也是如此 。 […]

所以我想你可以考虑这个在GCC和Clang中的错误。

不要从析构函数中抛出;)

这是一个错误,曾经,MSVC实际上是正确的:它打印“〜A”。

我修改了你的代码,我认为现在从输出中我们可以看到A没有被破坏。

 #include<iostream> using namespace std; struct A { ~A() { cout << "~A\n"; } A() { cout << "A()"; } }; struct B { ~B() noexcept( false ) { cout << "~B\n"; throw(0); } B() { cout << "B()"; } }; A foo() { B b; return; } int main() { try { foo(); } catch (...) {} } 

输出是:

B()A()〜乙

所以是的,这可能是一个错误。

Interesting Posts