char j; int* p1 =new (j) int; int* p2 =(int*) j;
How is the initialization of
p1 different from
p2 ? If there are no differences, then why do we need the
new operation with placement?
Placement-new calls the object's constructor, passing the specified address as
this . In other words, it creates an object at the specified address.
But placement-new can also be used for types without constructors (i.e. not classes), and for classes with trivial (doing nothing) constructors. The reason for this is not obvious:
In addition to the actual constructor call, placement-new has a second, more vague purpose. It creates an object, starts its lifetime (life).
Whether an object is alive or not cannot be determined by looking at the contents of the memory, this is an abstraction introduced in the standard. Placement-new for a type with no constructor (if no initializer is specified), or for a class (if a trivial constructor is called) compiles to 0 processor instructions, its effect is purely formal.
Trying to access an inanimate object causes undefined behavior, simply because the standard says so. Although, in practice, if your type is not a class, or a class with a trivial default constructor, it will often work just fine.
Placement-new returns a pointer to the newly created object. In your example,
p1 points to a freshly created
int , but
p2 doesn't , even though the pointer numbers are the same.
Why "does not indicate"? Because the standard says so. Attempting to read or write something to
*p2 will cause undefined behavior. However,
*std::launder(p2) will work.
Why is this undefined behavior needed? Probably to allow the compiler to perform tighter optimizations related to strict aliasing.