Ответ 1
Используйте ключевое слово alignas
:
alignas(Fred) char buf[sizeof(Fred)];
::new (static_cast<void*>(buf)) Fred;
Или используйте std::aligned_storage
, если вы предпочитаете библиотечную оболочку вокруг этой конструкции.
Согласно https://isocpp.org/wiki/faq/dtors#placement-new адрес, переданный в place-new, должен быть правильно выровнен. Но пример, который он дает, кажется, противоречит этому.
char memory[sizeof(Fred)];
Этот буфер, скорее всего, не выровнен для Fred, так как он немой char[]
, поэтому memory
может указывать на почти везде. Затем он размещает новые по этому адресу.
Является ли пример противоречащим требованию выравнивания, указанному в сноске DANGER?
Это приводит к связанному с ним вопросу:
Как создать буфер (стек или кучу) выровненный для типа T
(для использования в новом месте размещения одного или нескольких объектов T)?
В буфере я имею в виду буфер char[]
или void*
некоторого размера, а не T[]
, потому что это будет распределение объектов, которое впоследствии побеждает точку после размещения. new.
Спасибо.
Используйте ключевое слово alignas
:
alignas(Fred) char buf[sizeof(Fred)];
::new (static_cast<void*>(buf)) Fred;
Или используйте std::aligned_storage
, если вы предпочитаете библиотечную оболочку вокруг этой конструкции.
О вашем первом вопросе: в соответствии с ответами на этот связанный вопрос да, пример получил это неправильно:
Статически распределенные массивы выравниваются по байтам sizeof (element_type) - для char это 1 байт, который в основном не гарантирует выравнивания.
таким образом, массив char memory[sizeof(Fred)]
не имеет гарантий выравнивания для Fred
.
Правильный способ сделать это следующим образом (С++ 11):
alignas(Fred) char memory[sizeof(Fred)];
Для распределений кучи просто используйте std::malloc
, который гарантированно выделяет память, которая выровнена для любого типа.
Для распределения стека, если у вас есть доступ к С++ 11, вы можете использовать alignas
, как в
alignas(T) uint8_t data[sizeof(T)];
Если у вас нет доступа к С++ 11, вы должны вернуться к конкретным атрибутам компилятора как GCC __attribute__((aligned(N)))
.