Подтвердить что ты не робот

Действительно ли новый 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 говорит, что расширенные выравнивания могут поддерживаться, поэтому может ли компилятор самостоятельно решить, что класс является перенастраиваемым типом?

4b9b3361

Ответ 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 байты.