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>
#include <new>
template<std::size_t N>
struct MyAllocator
{
std::byte data[N];
std::size_t sz{N};
void* p{data};
MyAllocator() = default;
// Note: only well-defined for implicit-lifetime types
template<typename T>
T* implicit_aligned_alloc(std::size_t a = alignof(T))
{
if (std::align(a, sizeof(T), p, sz))
{
T* result = std::launder(reinterpret_cast<T*>(p));
p = static_cast<std::byte*>(p) + sizeof(T);
sz -= sizeof(T);
return result;
}
return nullptr;
}
};
int main()
{
MyAllocator<64> a;
std::cout << "allocated a.data at " << (void*)a.data
<< " (" << sizeof a.data << " bytes)\n";
// Allocate a char
if (char* p = a.implicit_aligned_alloc<char>())
{
*p = 'a';
std::cout << "allocated a char at " << (void*)p << '\n';
}
// Allocate an int
if (int* p = a.implicit_aligned_alloc<int>())
{
*p = 1;
std::cout << "allocated an int at " << (void*)p << '\n';
}
// Allocate an int, aligned at a 32-byte boundary
if (int* p = a.implicit_aligned_alloc<int>(32))
{
*p = 2;
std::cout << "allocated an int at " << (void*)p << " (32-byte alignment)\n";
}
}
Возможный вывод:
allocated a.data at 0x7ffc654e8530 (64 bytes) allocated a char at 0x7ffc654e8530 allocated an int at 0x7ffc654e8534 allocated an int at 0x7ffc654e8540 (32-byte alignment)
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были применены задним числом к ранее опубликованным стандартам C++.
| Отчёт об ошибке | Применяется к | Опубликованное поведение | Корректное поведение |
|---|---|---|---|
| LWG 2377 | C++11 |
alignment требовалось, чтобы было фундаментальным или поддерживаемым расширенным значением выравнивания | должно быть только степенью двойки |
См. также
alignof (C++11) | запрашивает требования к выравниванию типа (оператор) |
alignas (C++11) | указывает, что память для переменной должна быть выровнена на заданную величину (спецификатор) |
|
(начиная с C++11)(устарело в C++23) | определяет тип, подходящий для использования в качестве неинициализированной памяти для типов заданного размера (шаблон класса) |
|
(C++20) | сообщает компилятору, что указатель выровнен (шаблон функции) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/memory/align