cppreference† states that:
Objects with trivial default constructors can be created by using
reinterpret_cast
on any suitably aligned storage, e.g. on memory allocated withstd::malloc
.
This implies that the following is well-defined code:
struct X { int x; };
alignas(X) char buffer[sizeof(X)]; // (A)
reinterpret_cast<X*>(buffer)->x = 42; // (B)
Three questions follow:
- Is that quote correct?
- If yes, at what point does the lifetime of the
X
begin? If on line(B)
, is it the cast itself that is considered acquiring storage? If on line(A)
, what if there were a branch between(A)
and(B)
that would conditionally construct anX
or some other pod,Y
? - Does anything change between C++11 and C++1z in this regard?
†Note that this is an old link. The wording was changed in response to this question. It now reads:
Unlike in C, however, objects with trivial default constructors cannot be created by simply reinterpreting suitably aligned storage, such as memory allocated with
std::malloc
: placement-new is required to formally introduce a new object and avoid potential undefined behavior.
char*
can alias anything, but anything can't aliaschar*
– Blanchettestd::variant
orboost::variant
for example. The storage can't be allocated with a union because there's no way to build a union from a type list. So you use a std::aligned_storage, which is simply an aligned char buffer that is at least as big and as aligned as the most restrictive type in the type list. – Skinconstexpr
. – Betteanne