In section except.ctor, the rule states:
- As control passes from the point where an exception is thrown to a handler, objects with automatic storage duration are destroyed by a process, specified in this subclause, called stack unwinding.
- [...]
- If the initialization or destruction of an object other than by delegating constructor is terminated by an exception, the destructor is invoked for each of the object's direct subobjects and, for a complete object, virtual base class subobjects, whose initialization has completed ([dcl.init]) and whose destructor has not yet begun execution, except that in the case of destruction, the variant members of a union-like class are not destroyed. [ Note: If such an object has a reference member that extends the lifetime of a temporary object, this ends the lifetime of the reference member, so the lifetime of the temporary object is effectively not extended. — end note ] The subobjects are destroyed in the reverse order of the completion of their construction. Such destruction is sequenced before entering a handler of the function-try-block of the constructor or destructor, if any.
According to bullet 3, which states can be also considered as a part of the process of stack unwinding. Since the first rule sounds like that the invocation of stack unwinding is only for the object with automatic storage duration. Doesn't that stack unwinding invoke for the object with dynamic storage duration or others duration?
#include <iostream>
struct A{
~A(){
std::cout<<"invoke\n";
}
};
struct B{
B(){
throw 0;
}
A a;
};
int main(){
try{
auto ptr = new B{};
}catch(int){
}
}
Obviously, the subobject a occupies the storage within the complete object of the type B which has the dynamic storage duration. In my mind, A's destructor should be invoked since it has been completely constructed in the initialization of B. Both GCC and Clang agree that. Is it an extension of these compilers? How to interpret it?