Search code examples
c++c++11placement-new

Is previously initialize memory guaranteed to persist after a placement new call?


Say I have the following:

struct A
{
   int x;
};

//...
A* aOriginal = new A();  //value construct aOriginal
assert( aOriginal->x == 0 );

A* aSecond = new (aOriginal) A;
assert( aSecond->x == 0 );

Is the second assert guaranteed to hold, even though aSecond is not value-initialized? Logically, it should, because the memory isn't overwritten, but is it specified by the standard?


Solution

  • No.

    When you construct the second object on the same storage location, the lifetime of the previous one ends (§3.8/1):

    [...] The lifetime of an object of type T ends when:

    • if T is a class type with a non-trivial destructor (§12.4), the destructor call starts, or
    • the storage which the object occupies is reused or released.

    When the second object is created, since A has the implicit default constructor, the x member is default-initialized, and thus no initialization is performed (§8.5/6):

    To default-initialize an object of type T means:

    • [...]

    • otherwise, no initialization is performed.

    And this means the object has indeterminate value (§5.3.4/15):

    A new-expression that creates an object of type T initializes that object as follows:

    • If the new-initializer is omitted, the object is default-initialized (§8.5); if no initialization is performed, the object has indeterminate value.

    And in case you think that the value is not indeterminate because you previously initialized another object on that storage location: the standard discards that possibility as well by saying the properties of the previous object no longer apply once its lifetime ends (§3.8/3):

    The properties ascribed to objects throughout this International Standard apply for a given object only during its lifetime.