This is a follow-up to this question. Suppose I have this code:
class Class {
public virtual method()
{
this->~Class();
new( this ) Class();
}
};
Class* object = new Class();
object->method();
delete object;
which is a simplified version of what this answer suggests.
Now once a destructor is invoked from within method()
the object lifetime ends and the pointer variable object
in the calling code becomes invalid. Then the new object gets created at the same location.
Does this make the pointer to the object in the calling valid again?
This is explicitly approved in 3.8:7:
3.8 Object lifetime [basic.life]
7 - If, after the lifetime of an object has ended [...], a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object [...] can be used to manipulate the new object, if: (various requirements which are satisfied in this case)
The example given is:
struct C {
int i;
void f();
const C& operator=( const C& );
};
const C& C::operator=( const C& other) {
if ( this != &other ) {
this->~C(); // lifetime of *this ends
new (this) C(other); // new object of type C created
f(); // well-defined
}
return *this;
}
Strictly, this is fine. However, without extreme care, it will become a hideous piece of UB. For example, any derived classes calling this method won't get the right type re-constructed- or what happens if Class()
throws an exception. Furthermore, this doesn't really accomplish anything.
It's not strictly UB, but is a giant pile of crap and fail and should be burned on sight.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With