Действительно ли новый char гарантирует согласованную память для типа класса?
Является ли выделение буфера через new char[sizeof(T)]
гарантией выделение памяти, которая правильно выровнена для типа T
, где все члены T
имеют свою естественную, определенную реализацию, выравнивание (т.е. вы не использовали alignas
, чтобы изменить их выравнивание).
Я видел эту гарантию в нескольких ответах здесь, но я не совсем понимаю, как стандарт достигает этой гарантии. 5.3.4-10 стандарта дает основное требование: по существу new char[]
должен быть выровнен с max_align_t
.
То, что мне не хватает, это бит, который говорит, что alignof(T)
всегда будет правильным выравниванием с максимальным значением max_align_t
. Я имею в виду, это кажется очевидным, но должно ли получившееся выравнивание структуры быть не более max_align_t
? Даже точка 3.11-3 говорит, что расширенные выравнивания могут поддерживаться, поэтому может ли компилятор самостоятельно решить, что класс является перенастраиваемым типом?
Ответы
Ответ 1
То, что мне не хватает, это бит, который говорит, что alignof(T)
всегда будет правильным выравниванием с максимальным значением max_align_t
. Я имею в виду, это кажется очевидным, но должно ли получившееся выравнивание структуры быть не более max_align_t
? Даже точка 3.11-3 говорит, что расширенные выравнивания могут поддерживаться, поэтому может ли компилятор самостоятельно решить, что класс является перенастраиваемым типом?
Как заметил Манкарсе, лучшая цитата, которую я мог получить, - от [basic.align]/3:
Тип, имеющий расширенное требование выравнивания, является выровненным типом. [ Заметка: каждый выровненный тип имеет или содержит тип класса, к которому применяется расширенное выравнивание (возможно, через нестатический элемент данных). -end note]
который, по-видимому, подразумевает, что расширенное выравнивание должно быть явно потребовано (а затем распространяется), но не может
Я бы предпочел более четкое упоминание; намерение очевидно для компилятора-писателя, и любое другое поведение будет безумным, все еще...
Ответ 2
Выражения new char[N]
и new unsigned char[N]
гарантированы
чтобы вернуть память, достаточно выровненную для любого объекта. См. §5.3.4/10
"[...] Для массивов char и unsigned char разница между
результат нового выражения и адрес, возвращаемый распределением
функция должна быть целым кратным строжайшей фундаментальной
(3.11) любого типа объекта, размер которого не больше
чем размер создаваемого массива. [Примечание: поскольку распределение
предполагается, что функции возвращают указатели на
надлежащим образом выровнены для объектов любого типа с фундаментальными
выравнивание, это ограничение на служебные данные распределения массива позволяет
общая идиома выделения массивов символов, в которые объекты других
типы будут позже размещены. -end note] ".
С стилистической точки зрения, конечно: если вы хотите выделить raw
памяти, яснее сказать: operator new(N)
. Концептуально,
new char[N]
создает N
char
; operator new(N)
выделяет N
байты.