Namespaces
Variants

std:: align

From cppreference.net
Memory management library
( exposition only* )
Allocators
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Memory resources
Uninitialized storage (until C++20)
( until C++20* )
( until C++20* )
( until C++20* )

Garbage collector support (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
Определено в заголовочном файле <memory>
void * align ( std:: size_t alignment,

std:: size_t size,
void * & ptr,

std:: size_t & space ) ;
(начиная с C++11)

Дано указатель ptr на буфер размером space , возвращает указатель, выровненный по заданному alignment для size количества байт и уменьшает аргумент space на количество байт, использованных для выравнивания. Возвращается первый выровненный адрес.

Функция изменяет указатель только в том случае, если в буфере возможно разместить требуемое количество байт, выровненных по заданному alignment. Если буфер слишком мал, функция не выполняет никаких действий и возвращает 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;
    // Примечание: корректно определено только для типов с неявным временем жизни
    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";
    // Выделение памяти для char
    if (char* p = a.implicit_aligned_alloc<char>())
    {
        *p = 'a';
        std::cout << "allocated a char at " << (void*)p << '\n';
    }
    // Выделение памяти для int
    if (int* p = a.implicit_aligned_alloc<int>())
    {
        *p = 1;
        std::cout << "allocated an int at " << (void*)p << '\n';
    }
    // Выделение памяти для int с выравниванием по 32-байтной границе
    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++.

DR Применяется к Поведение в опубликованной версии Корректное поведение
LWG 2377 C++11 alignment required to be a fundamental or supported extended alignment value only need to be a power of two

Смотрите также

alignof (C++11) запрашивает требования к выравниванию типа
(оператор)
alignas (C++11) указывает, что память для переменной должна быть выровнена на определенное значение
(спецификатор)
(since C++11) (deprecated in C++23)
определяет тип, подходящий для использования в качестве неинициализированного хранилища для типов заданного размера
(шаблон класса)
информирует компилятор о том, что указатель выровнен
(шаблон функции)