I want to construct B
at the place for A
.
struct A {
size_t x; // 8 bytes
int i; // 4 bytes
}; // padding 4 bytes
struct B {
size_t x; // 8 bytes
bool b; // 1 byte
}; // padding 7 bytes
int main() {
A a;
auto p = new(&a) B;
// auto p = new(std::launder(&a)) B; // is a bit better
}
Is this code well-defined? Will placement new
touch padding bytes (e.g. set all to zeros) or it will work directly with the b
bytes?
For example, two A
structures are stored contiguously (right after first A::i
goes second A::x
). If placement new
touches padding, second A
's data will be corrupted.
There are several things to discuss here.
First off, padding is in general unspecified, so you should not assume that you know what and where the padding is. The main constraints are that
T[N]
has size N * sizeof(T)
, i.e. there is no "extra array padding". This gives you some minimum padding consequences for T
.This means that your "right after first A::i
goes second A::st
" can't be done; this is not something you get to decide.
The placement-new can reuse existing storage, and the main requirement is that the storage is both large enough and suitably aligned for the destination type. You can statically assert these things with sizeof
and alignof
. The result of the placement-new expression is that the target object (of type B
in your example) is initialized (as requested by the chosen initialization syntax), which will potentially write to any and all of the storage occupied by the B
object. As per the above requirements, those will be wholly contained within the provided storage, or you already have UB.
If you want a whole array A[N]
to provide storage for some sequence of objects, then of course it's possible in principle to overwrite the storage of multiple adjacent A
objects, but as long as each B
object is placement-new-constructed into one specific A
object and that one provides sufficient storage (as described above), then no one B
object will invalidate any unrelated underlying A
objects.