Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does destroying and recreating an object make all pointers to this object invalid?

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?

like image 980
sharptooth Avatar asked Sep 20 '12 12:09

sharptooth


2 Answers

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;
}
like image 81
ecatmur Avatar answered Oct 17 '22 15:10

ecatmur


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.

like image 44
Puppy Avatar answered Oct 17 '22 14:10

Puppy