Spec-Zone.ru › C++

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) указывает, что память для переменной должна быть выровнена на заданную величину
(спецификатор)
aligned_storage
(начиная с C++11)(устарело в C++23)
определяет тип, подходящий для использования в качестве неинициализированной памяти для типов заданного размера
(шаблон класса)
assume_aligned
(C++20)
сообщает компилятору, что указатель выровнен
(шаблон функции)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/memory/align

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API