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