默认析构函数nothrow [英] Default destructor nothrow

查看:464
本文介绍了默认析构函数nothrow的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码不会在gcc-4.7.1下编译,而是在clang-3.2下编译。哪一个遵循C ++ 11标准?

The following code doesn't compile under gcc-4.7.1 but compile under clang-3.2. Which one follows the C++11 standard?

struct X {
  virtual ~X() = default;
};

struct Y : X {
  virtual ~Y() = default;
};

gcc-4.7.1抱怨:

gcc-4.7.1 complains that:

looser throw specifier for 'virtual Y::~Y()'
error: overriding 'virtual X::~X() noexcept(true)'

显然,gcc-4.7.1认为X的默认析构函数nothrow,但Y的默认析构函数不是nothrow。为什么是这样?任何人都可以参考标准的正确的地方吗?谢谢。

Obviously, gcc-4.7.1 thinks X's default destructor nothrow, but Y's default destructor is not nothrow. Why is this? Can anyone refer to the correct place in standard? Thanks.

我在stackoverflow上看到了类似的问题,但我没有看到标准的答案。

I saw similar questions on stackoverflow, but I didn't see the answers refering to the standard.

推荐答案

编译器陷入困境,原因如下:

在函数声明中不指定任何异常(即不使用 throw noexcept )意味着允许该函数抛出所有可能的异常:

(1) Not specifying any exceptions in a function declaration (i.e. not using throw nor noexcept) means to allow that function to throw all possible exceptions:


(§15.4/函数与无异常规范或具有 noexcept(constant-expression)形式的异常规范 [...]

(§15.4/12, emphasis mine) A function with no exception-specification or with an exception-specification of the form noexcept(constant-expression) where the constant-expression yields false allows all exceptions. [...]

(2)默认析构函数必须允许由其隐式定义直接调用的函数允许的异常:

(2) A default destructor must allow exactly the exceptions that are allowed by the functions directly invoked by its implicit definition:


(§15.4/ 14,强调我)隐式声明的特殊成员函数(第12条)应该有一个异常规范。 如果f是隐式声明的默认构造函数,复制构造函数,移动构造函数,析构函数,复制赋值运算符或移动赋值运算符< type-id T当且仅当通过f的隐式定义直接调用的函数的异常规范允许T时; f将允许所有异常,如果它直接调用的任何函数允许所有异常,并且f将不允许任何异常,如果它直接调用的每个函数不允许异常。

(§15.4/14, emphasis mine) An implicitly declared special member function (Clause 12) shall have an exception-specification. If f is an implicitly declared default constructor, copy constructor, move constructor, destructor, copy assignment operator, or move assignment operator, its implicit exception-specification specifies the type-id T if and only if T is allowed by the exception-specification of a function directly invoked by f’s implicit definition; f shall allow all exceptions if any function it directly invokes allows all exceptions, and f shall allow no exceptions if every function it directly invokes allows no exceptions.


$ b b

(3)当特殊成员(例如析构函数)被显式默认时,即当你使用 = default 规格为可选(请参阅下面的可能有的使用):

(3) When a special member (such as a destructor) is explicitly defaulted, i.e. when you use = default, the exception specification is optional (see the use of "may have" below):


可能具有明确的异常规范,只有在兼容的情况下才能使用(15.4)与隐式声明的异常规范。 [...]

(8.4.2/2, emphasis mine) An explicitly-defaulted function [...] may have an explicit exception-specification only if it is compatible (15.4) with the exception-specification on the implicit declaration. [...]

在标准中没有要求在显式默认析构函数中指定异常的语句。

There is no statement in the Standard that requires the exception specification in an explicitly defaulted destructor.

结论:因此,不指定异常的显式默认析构函数可以通过两种方式解释:

Conclusion: Therefore, not specifiying the exceptions of an explicitly defaulted destructor can be interpreted in two ways:


  • 表示(根据上述第(1)项)
  • 或者,或者,意味着完全相同的异常被允许与析构函数的隐式默认定义(根据上面的(3)),在你的情况下意味着允许没有异常(根据上面的(2))。
  • To mean that all exceptions are allowed (according to (1) above)
  • Or, alternatively, to mean that exactly the same exceptions are allowed as are allowed by the implicit default definition of the destructor (according to (3) above), which in your case means to allow no exceptions (according to (2) above).

不幸的是,GCC以一种方式解决了这种困境无异常)在您的基类声明的情况下,并以不同的方式在派生类(有利于所有异常的情况下)。

Unfortunately, GCC resolves this dilemma in one way (in favor of "no exceptions") in the case of your base class declaration, and in a different way in the case of the derived class (in favor of "all exceptions" there).

我相信这个公认的模糊情况的最自然的解释是假设(2)和(3)重写(1)。标准没有这样说,但它应该。根据这种解释,Clang似乎就在这里。

I believe the most natural interpretation of this admittedly ambiguous situation is to assume that (2) and (3) override (1). The Standard does not say so, but it should. Under that interpretation, Clang seems to be right here.

这篇关于默认析构函数nothrow的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆