std::align
| Определено в заголовочном файле <memory>
|
||
void* align( std::size_t alignment, std::size_t size, void*& ptr, std::size_t& space ); |
(начиная с 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) |
сообщает компилятору, что указатель выровнен (шаблон функции) |