Search code examples
c++dynamic-memory-allocationplacement-newobject-construction

Do we really need placement new-expressions?


I am trying to understand placement new-expressions in C++.

This Stack Overflow answer states that T* p = new T(arg); is equivalent to

void* place = operator new(sizeof(T));  // storage allocation
T* p = new(place) T(arg);               // object construction

and that delete p; is equivalent to

p->~T();             // object destruction
operator delete(p);  // storage deallocation

Why do we need the placement new-expression in T* p = new(place) T(arg); for object construction, isn’t the following equivalent?

T* p = (T*) place;
*p = T(arg);

Solution

  • The first thing to note is that *p = T(arg); is an assignment, not a construction.

    Now let's read the standard ([basic.life]/1):

    ... The lifetime of an object of type T begins when:

    • storage with the proper alignment and size for type T is obtained, and
    • its initialization (if any) is complete (including vacuous initialization)

    For a general type T, initialization could have been completed if placement new were used, but that's not the case. Doing

    void* place = operator new(sizeof(T));
    T* p = (T*)place;
    

    doesn't start the lifetime of *p.

    The same section reads ([basic.life]/6):

    ... Before the lifetime of an object has started but after the storage which the object will occupy has been allocated ... any pointer that represents the address of the storage location where the object will be ... located may be used but only in limited ways. ... The program has undefined behavior if: ...

    • the pointer is used to access a non-static data member or call a non-static member function of the object, ...

    operator= is a non-static member function and doing *p = T(arg);, which is equivalent to p->operator=(T(arg)), results in undefined behaviour.

    A trivial example is a class that contains a pointer as a data member that is initialized in the constructor and is dereferenced in the assignment operator. Without placement new the constructor won't be called and that pointer won't be initialized (complete example).