std::align
Определено в заголовочном файле <memory>
|
||
void* align( std::size_t alignment, std::size_t size, |
(начиная с C++11) | |
Учитывая указатель ptr на буфер размером space, возвращает указатель, выровненный по указанному alignment для числа байтов size, и уменьшает аргумент space по количеству байтов, используемых для выравнивания. Возвращается первый выровненный адрес.
Функция изменяет указатель только в том случае, если можно было бы поместить в буфер требуемое количество байтов, выровненных по заданному выравниванию. Если буфер слишком мал, функция ничего не делает и возвращает nullptr.
Поведение не определено, если alignment не является степенью двойки.
Содержание |
[править] Параметры
alignment | — | желаемое выравнивание |
size | — | размер хранилища для выравнивания |
ptr | — | указатель на непрерывное хранилище (буфер) размером не менее space байт
|
space | — | размер буфера для операции |
[править] Возвращаемое значение
Скорректированное значение ptr или значение нулевого указателя, если предоставленное пространство слишком мало.
[править] Пример
Демонстрирует использование std::align
для размещения в памяти объектов разных типов.
#include <iostream> #include <memory> template<std::size_t N> struct MyAllocator { char data[N]; void* p; std::size_t sz; MyAllocator() : p(data), sz(N) {} template<typename T> T* aligned_alloc(std::size_t a = alignof(T)) { if (std::align(a, sizeof(T), p, sz)) { T* result = reinterpret_cast<T*>(p); p = (char*)p + sizeof(T); sz -= sizeof(T); return result; } return nullptr; } }; int main() { MyAllocator<64> a; std::cout << "распределяет a.data в " << (void*)a.data << " (" << sizeof a.data << " байт)\n"; // распределяет char if (char* p = a.aligned_alloc<char>()) { *p = 'a'; std::cout << "распределяет char в " << (void*)p << '\n'; } // распределяет int if (int* p = a.aligned_alloc<int>()) { *p = 1; std::cout << "распределяет int в " << (void*)p << '\n'; } // распределяет int, выровненный по 32-байтовой границе if (int* p = a.aligned_alloc<int>(32)) { *p = 2; std::cout << "распределяет int в " << (void*)p << " (выравнивание по 32 байтам)\n"; } }
Возможный вывод:
распределяет a.data в 0x7ffd0b331f80 (64 байт) распределяет char в 0x7ffd0b331f80 распределяет int в 0x7ffd0b331f84 распределяет int в 0x7ffd0b331fa0 (выравнивание по 32 байтам)
[править] Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
Номер | Применён | Поведение в стандарте | Корректное поведение |
---|---|---|---|
LWG 2377 | C++11 | alignment должен быть основным или поддерживаемымрасширенным значением выравнивания |
должен быть только степенью двойки |
[править] Смотрите также
оператор alignof (C++11)
|
запрашивает требования к выравниванию типа |
спецификатор alignas (C++11)
|
указывает, что хранилище для переменной должно быть выровнено на определённую величину |
(C++11)(устарело в C++23) |
определяет тип, подходящий для использования в качестве неинициализированного хранилища для типов заданного размера (шаблон класса) |
(C++20) |
сообщает компилятору, что указатель выровнен (шаблон функции) |