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?
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.
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