#опытным
alignas задает требования к выравниваю для типа или переменной. И компилятор, при размещении объектов на стеке слушает и повинуется этим правилам.
Но, например, malloc следует только своим внутренним правилам. Он выравнивает адреса, но только по границе alignof(std::max_align_t]). Это 16 байт на современных десктопах.
Что делать, если мне нужны более строгие требования к адресу? Например нужно выровнять выделенные на куче данные по границе 32, 64 или вообще по размеру страницы 4096 байт?
Для этого используется С++17 функция aligned_alloc:
void* aligned_alloc( std::size_t alignment, std::size_t size);
где alignment - требования к выравниванию, а size - размер данных для аллокации в байтах. size должен быть кратным alignment. Функция выделяет просто size байт и не конструирует никаких объектов. Подразумевается также возможность выделить массив значений размером size/alignment, каждое из которых выравнено по границе alignment.
Используется это в аллокаторах, если нужно учитывать выравнивание выделяемой памяти:
template <typename T>
T *allocate_aligned(size_t count) {
if (count == 0)
return nullptr;
const size_t alignment = alignof(T);
const size_t type_size = sizeof(T);
const size_t total_bytes = count * type_size;
char *raw_memory =
static_cast<char *>(std::aligned_alloc(alignment, total_bytes));
if (!raw_memory)
throw std::bad_alloc();
for (size_t constructed = 0; constructed < count; ++constructed) {
new (raw_memory + (constructed * type_size)) T();
}
return reinterpret_cast<T *>(raw_memory);
}
С аллокаторами тут полет фантазий может далеко увести, но суть такая: если нужна по-особенному выравненная динамическая память - используем std::aligned_alloc.
Align yourself. Stay cool.
#cppcore #cpp17 #compiler