[C++ job interview Q&A] Throwing an exception from a destructor.
It’s important to know what happens on throwing an exception from class’ destructor. Is it a good practice? What errors may it generate?
Like any other function, destructor may throw exceptions. However, if no exception specification is declared, then – usually – it is set to noexcept(true). In order to have a throwing destructor, it must be explicitly declared noexcept(false).
What happens on throwing an exception from a destructor? If its exception specification is implicit or declared noexcept(true), then it behaves like all other noexcept functions. A throw expression causes an immediate call to std::terminate. Next, it causes a call to std::abort – the abnormal program termination in implementation-defined manner.
If the exception specification of a destructor is explicitly declared noexcept(false), then it is possible to successfully throw an exception from it. Although, this is a bad practice. There are at least two significant problems.
Firstly, destructors are supposed to release all resources owned by an object. Handling exceptional cases there may complicate the code and introduce errors.
It also complicates exception handling in the whole program’s code. Once an exception is thrown, the control flow works backwards, calling destructors of e.g. local objects, until it reaches the try-catch block that is able to handle the exception. This is called stack unwinding. When another exception is thrown during that process (i.e. from a destructor of a local object), std::terminate is immediately called. Again, it makes the program to close in an implementation-defined manner.
In some cases, throwing an exception from a destructor might be a useful trick. Although, such an approach shall be well thought and justified.