Reading in the cppreference for lifetime, there is the following statement for storage reuse
A program is not required to call the destructor of an object to end its lifetime if the object is trivially-destructible or if the program does not rely on the side effects of the destructor. However, if a program ends the lifetime of an non-trivially destructible object that is a variable explicitly, it must ensure that a new object of the same type is constructed in-place (e.g. via placement new) before the destructor may be called implicitly, i.e. due to scope exit or exception for automatic objects, due to thread exit for thread-local objects, or due to program exit for static objects; otherwise the behavior is undefined.
There is the following example
class T {}; // trivial
struct B
{
~B() {} // non-trivial
};
void x()
{
long long n; // automatic, trivial
new (&n) double(3.14); // reuse with a different type okay
} // okay
void h()
{
B b; // automatic non-trivially destructible
b.~B(); // end lifetime (not required, since no side-effects)
new (&b) T; // wrong type: okay until the destructor is called
} // destructor is called: undefined behavior
Why when the destructor of T is called is undefined behavior?
In the above example, if std::launder is used , is the UB issue solved? Look at the following demo