I'm trying to figure out whether the following is undefined behaviour. I have a feeling it's not UB, but my reading of the standard makes it look like it is UB:
#include <iostream>
struct A {
A() { std::cout << "1"; }
~A() { std::cout << "2"; }
};
int main() {
A a;
new (&a) A;
}
Quoting the C++11 standard:
basic.life¶4 says "A program may end the lifetime of any object by reusing the storage which the object occupies"
So after new (&a) A
, the original A
object has ended its lifetime.
class.dtor¶11.3 says that "Destructors are invoked implicitly for constructed objects with automatic storage duration ([basic.stc.auto]) when the block in which an object is created exits ([stmt.dcl])"
So the destructor for the original A
object is invoked implicitly when main
exits.
class.dtor¶15 says "the behavior is undefined if the destructor is invoked for an object whose lifetime has ended ([basic.life])."
So this is undefined behaviour, since the original A
no longer exists (even if the new a
now exists in the same storage).
The question is whether the destructor for the original A
is called, or whether the destructor for the object currently named a
is called.
I am aware of basic.life¶7, which says that the name a
refers to the new object after the placement new
. But class.dtor¶11.3 explicitly says that it's the destructor of the object which exits scope which is called, not the destructor of the object referred to by a name that exits scope.
Am I misreading the standard, or is this actually undefined behaviour?
Edit: Several people have told me not to do this. To clarify, I'm definitely not planning on doing this in production code! This is for a CppQuiz question, which is about corner cases rather than best practices.