我有以下代码:
#include#include struct ok { int _n; ok(int n) : _n(n) { std::cerr <<"OK" < 我看到他没有调用ok {3}的析构函数,输出是:
OK1 born OK2 born OK3 born OK2 gone OK1 gone这是C++ 14的预期行为吗?
编辑:
用gcc 6.3编译
1> P.W..:根据标准,这种行为是错误的,这已经在问题的评论部分中提到过.这在" 异常处理 "一节中说明.
按照该缺陷报告在open-std.org,他们已经意识到,实现(GCC和锵)是错误的这一点,早在2015年9月28日.但提议的决议仅在2016年2月,编制者(GCC和Clang)尚未包含此修复.
拟议决议(2016年2月):
更改18.2 [except.ctor]第2段如下:
由于输入了try块,因此构造但尚未销毁的类类型的每个自动对象都会调用析构函数.如果在销毁临时语句或局部变量的过程中抛出异常(9.6.3 [stmt.return]),则还会调用返回对象(如果有)的析构函数.对象以完成构造的相反顺序销毁.[例:struct A { }; struct Y { ~Y() noexcept(false) { throw 0; } }; A f() { try { A a; Y y; A b; return {}; // #1 } catch (...) { } return {}; // #2 }在#1处,构造了类型A的返回对象.然后,销毁局部变量b(9.6 [stmt.jump]).接下来,局部变量y被销毁,导致堆栈展开,导致返回对象的破坏,然后销毁局部变量a.最后,返回的对象再次在#2处构建. - 末端的例子]
在GCC和Clang都有针对这个问题提出的错误.
关于GCC错误报告的评论表明它显然是一个错误.
乔纳森威克利评论:
它现在是2013年所以,如果您的析构函数可以抛出,那么明智的做法就是不返回值.
另一个用户:
是的,我注意到了,而Clang也有一个针对他们的错误,这些错误已经萎缩多年.然而,这种行为是错误的.