Вся поддержка расширенного выравнивания определяется реализацией :
Определяется реализацией, поддерживаются ли какие-либо расширенные выравнивания и контексты, в которых они поддерживаются .
Добавлено выделение.
Реализация свободна для поддержки расширенных выравниваний в некоторых местах, но не в других.Возможно, будет хорошо создать объект кучи с расширенным выравниванием, но не объект стека (или как подобъект переменной стека).aligned_storage
- это просто другой контекст.
, почему [расширенное выравнивание] является реализацией, определенной в некоторых контекстах, где она должна быть четко определена (например, память стека)?
Рассмотрим бремя реализации распределения кучи по сравнению с выделением стека.
Что нужно сделать компилятору для работы new OverAlignedType
с распределением кучи?Pre-C ++ 17?Требуется ничего .Либо ::operator new
просто так будет выделять хранилище, подходящее для этого выравнивания или неопределенных результатов поведения.Компилятор имеет нулевой контроль над этим.То же самое касается размещения - new
;в этом случае пользователь должен правильно его выровнять.
C ++ 17 добавил выровненные формы operator new
.Но даже тогда единственная разница в том, какая версия функции вызывается.Это довольно просто для реализации компилятором.
Теперь рассмотрим распределение в стеке.Я создаю переменную типа OverAlignedType
.Хорошо, так как это будет реализовано?Очевидно, компилятор смотрит на то, где будет смещение стека в этой точке функции, основываясь на предыдущих выделениях в стеке.Тогда это -
Неверно! Почему?Поскольку выравнивание фактического адреса для того места, где начался стек в этом вызове функции, может не подходить для этого типа.Помните: для любого данного вызова функции адрес стека будет зависеть от того, каким будет текущий граф вызовов.Если ваш OverAlignedType
требует 32-байтового выравнивания, а ABI требует только 16-байтового выравнивания для начала стека, очень возможно, что иногда пользователь вызывает его, когда стек будет на 32-граница байта, а иногда и 16-байтовая.
Так что вы делаете?Что ж, вам нужно выполнить некоторый код времени выполнения , чтобы посмотреть на реальный адрес стека и выровнять его там, где это необходимо.Обратите внимание, что это превращает статическое смещение во время компиляции в динамическое.Это также может повлиять на размещение каждого стекового объекта в этой функции.
Или вы можете просто запретить пользователю использовать в стеке перегруженные типы.