Поиск…


Вступление

Все типы в C ++ имеют выравнивание. Это ограничение на адрес памяти, в котором объекты этого типа могут быть созданы внутри. Адрес памяти действителен для создания объекта, если разделение этого адреса на выравнивание объекта является целым числом.

Выравнивание типов всегда имеет силу двух (включая 1).

замечания

Стандарт гарантирует следующее:

  • Требование к выравниванию типа является делителем его размера. Например, класс с размером 16 байт может иметь выравнивание 1, 2, 4, 8 или 16, но не 32. (Если члены класса имеют всего 14 байтов, но класс должен иметь требование выравнивания из 8, компилятор будет вставлять 2 байта заполнения, чтобы размер класса был равен 16.)
  • Подписанные и неподписанные версии целочисленного типа имеют одинаковое требование выравнивания.
  • Указатель на void имеет такое же требование выравнивания, как и указатель на char .
  • Квалифицированные и cv-неквалифицированные версии типа имеют одинаковое требование выравнивания.

Обратите внимание, что, хотя выравнивание существует в C ++ 03, только C ++ 11 стало возможным запрашивать выравнивание (используя alignof ) и выравнивание управления (используя alignas ).

Запрос выравнивания типа

C ++ 11

Требование выравнивания типа можно запросить с помощью alignof слова alignof в качестве унарного оператора. Результатом является постоянное выражение типа std::size_t , то есть оно может быть оценено во время компиляции.

#include <iostream>
int main() {
    std::cout << "The alignment requirement of int is: " << alignof(int) << '\n';
}

Возможный выход

Требование выравнивания int: 4

Если применяется к массиву, он дает требование выравнивания типа элемента. Если применяется к ссылочному типу, он дает требование выравнивания ссылочного типа. (У самих ссылок нет выравнивания, поскольку они не являются объектами.)

Управление выравниванием

C ++ 11

alignas слово alignas можно использовать для принудительной alignas переменной, члена данных класса, объявления или определения класса или объявления или определения перечисления, чтобы иметь конкретное выравнивание, если оно поддерживается. Это происходит в двух формах:

  • alignas(x) , где x является константным выражением, дает объекту выравнивание x , если поддерживается.
  • alignas(T) , где T - тип, дает объекту выравнивание, равное требованию выравнивания T , то есть alignof(T) , если поддерживается.

Если к alignas и тому же объекту применяются несколько alignas , применяется самый строгий.

В этом примере буфер buf гарантированно будет соответствующим образом выровнен для хранения объекта int , даже если его тип элемента является unsigned char , который может иметь более слабое требование выравнивания.

alignas(int) unsigned char buf[sizeof(int)];
new (buf) int(42);

alignas не может использоваться, чтобы дать типу меньшее выравнивание, чем тип имел бы без этого объявления:

alignas(1) int i; //Il-formed, unless `int` on this platform is aligned to 1 byte.
alignas(char) int j; //Il-formed, unless `int` has the same or smaller alignment than `char`.

alignas , если задано целочисленное постоянное выражение, должно быть дано правильное выравнивание. Допустимые выравнивания всегда равны двум и должны быть больше нуля. Компиляторы должны поддерживать все допустимые выравнивания до выравнивания типа std::max_align_t . Они могут поддерживать более крупные выравнивания, чем это, но поддержка выделения памяти для таких объектов ограничена. Верхний предел выравнивания зависит от реализации.

C ++ 17 поддерживает прямую поддержку operator new для выделения памяти для выверенных типов.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow