Why do I always get “terminate called after throwing an instance of…” when throwing in my destructor?

心已入冬 提交于 2019-12-05 08:19:49

In C++11 the noexcept keyword was added. This can be used in function exception specifications:

  • noexcept(true) is the same as throw(), i.e. this function terminates if anything is thrown
  • noexcept(false) means the function may throw anything

For most functions, they don't have an exception-specification unless you give them one. A function with no exception-specification may throw anything.

There is a special case for destructors though, found in C++11 [class.dtor]/3:

A declaration of a destructor that does not have an exception-specification is implicitly considered to have the same exception-specification as an implicit declaration (15.4).

The referenced rule, 15.4, says that implicitly-declared special member functions always have an exception-specification. The specification is determined by the following rule, [except.spec]/14:

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.

The "function it directly invokes" in this clause means the destructor of any member variable or base class (applied recursively). If there is no such function , then there are no exceptions allowed by such a function, so the default is noexcept(true).

We could summarise the portion of the above quote relating to your code like this:

  • If all subobjects either have no destructor, or implicitly-generated destructor, or destructor declared as noexcept(true) or equivalent; then this class's destructor defaults to noexcept(true).

So, changing your destructor to have noexcept(false) would reproduce the behaviour of C++03.


In C++03 none of this appeared and your destructor would have defaulted to allowing all exceptions. I don't know for sure why this change was made in C++11, but it may be because it is a bad idea to throw from a destructor unless you really know what you are doing.

detailed explanation available at http://www.parashift.com/c++-faq/dtors-shouldnt-throw.html. Better explanation than my own words :)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!