On Saturday, 12 December 2015 19:09:52 UTC+2, Daniel wrote:
> I'm trying to understand the rules for alignment with placement new.
>
> If we have
>
> struct A
> {
> size_t length;
> };
>
> my understanding (please correct me if I'm wrong) is that this results in a
> data structure that is properly aligned:
>
> typedef typename std::aligned_storage<sizeof(A),
> alignof(A)>::type storage_type;
>
> char* storage = new char [sizeof(storage_type)];
> A* pa = new(storage)A();
Seems that you pointlessly manufacture that 'storage_type' there.
// that looks better and works
storage_type* storage = new storage_type;
A* pa = new(storage)A();
// that also works since new provides maximally aligned storage
char* storage = new char [sizeof(A)];
A* pa = new(storage)A();
The likes of that 'storage_type' are typically used to reserve space
in automatic storage or as a data member of class:
// in automatic storage
storage_type storage;
A* pa = new(&storage) A();
>
> But what if we have
>
> struct B
> {
> size_t length;
> int *p;
> };
>
> and wish to allocate storage for B and p with placement new from the same storage?
>
> Does this satisfy alignment rules?
>
> typedef typename std::aligned_storage<sizeof(B),
> alignof(B)>::type storage_type;
>
> size_t length = 10;
> char* storage = new char [sizeof(storage_type)+length*sizeof(int)];
> B* pb = new(storage)B();
>
> pb->p = new(storage + sizeof(storage_type))int[length];
>
It isn't guaranteed that alignment requirements for 'int' are not stricter
than alignment requirements for that 'B'. It is unlikely that you can find
any C++11 compiler where these are stricter but world may change.
Also if there was 'long double' instead of 'int' then alignment requirements for it are often stricter than for the 'B' of yours and then your program
would not work correctly.
Following code is bit more paranoid about that possible padding. When
padding is zero then compiler will likely figure it out and optimize
away:
constexpr size_t padding = (alignof(int) - (sizeof(B) % alignof(int))) % alignof(int);
size_t length = 10;
char* storage = new char [sizeof(B) + padding + sizeof(int)*length];
B* pb = new(storage) B();
pb->length = length;
pb->p = new(storage + sizeof(B) + padding) int[length];