Yes, it is guaranteed (provided the exception is caught), down to the order in which the destructors are invoked:
C++11 15.2 Constructors and destructors [except.ctor]
1 As control passes from a throw-expression to a handler, destructors are invoked for all
automatic objects constructed since the try block was entered. The
automatic objects are destroyed in the reverse order of the completion
of their construction.
Furthermore, if the exception is thrown during object construction, the subobjects of the partially-constructed object are guaranteed to be correctly destroyed:
2 An object of any storage duration whose initialization or
destruction is terminated by an exception will have destructors
executed for all of its fully constructed subobjects (excluding the
variant members of a union-like class), that is, for subobjects for
which the principal constructor (12.6.2) has completed execution and
the destructor has not yet begun execution. Similarly, if the
non-delegating constructor for an object has completed execution and a
delegating constructor for that object exits with an exception, the
object’s destructor will be invoked. If the object was allocated in a
new-expression, the matching deallocation function (3.7.4.2, 5.3.4,
12.5), if any, is called to free the storage occupied by the object.
This whole process is known as "stack unwinding":
3 The process of calling destructors for automatic objects constructed
on the path from a try block to a throw-expression is called “stack
unwinding.” If a destructor called during stack unwinding exits with
an exception, std::terminate is called (15.5.1).
Stack unwinding forms the basis of the widely-used technique called Resource Acquisition Is Initialization (RAII).
Note that stack unwinding is not necessarily done if the exception is not caught. In this case it's up to the implementation whether stack unwinding is done. But whether stack unwinding is done or not, in this case you're guaranteed a final call to std::terminate
.
C++11 15.5.1 The std::terminate() function [except.terminate]
2 … In the situation where no matching handler is found,
it is implementation-defined whether or not the stack is unwound before std::terminate()
is called.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…