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>
 
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 << "allocated a.data at " << (void*)a.data
              << " (" << sizeof a.data << " bytes)\n";
 
    // allocate a char
    if (char* p = a.aligned_alloc<char>())
    {
        *p = 'a';
        std::cout << "allocated a char at " << (void*)p << '\n';
    }
 
    // allocate an int
    if (int* p = a.aligned_alloc<int>())
    {
        *p = 1;
        std::cout << "allocated an int at " << (void*)p << '\n';
    }
 
    // allocate an int, aligned at 32-byte boundary
    if (int* p = a.aligned_alloc<int>(32))
    {
        *p = 2;
        std::cout << "allocated an int at " << (void*)p << " (32 byte alignment)\n";
    }
}

Возможный вывод:

allocated a.data at 0x7ffd0b331f80 (64 bytes)
allocated a char at 0x7ffd0b331f80
allocated an int at 0x7ffd0b331f84
allocated an int at 0x7ffd0b331fa0 (32 byte alignment)

Отчеты об ошибках

Следующие отчеты об ошибках, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применено к Поведение, опубликованное Корректное поведение
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/w/cpp/memory/align

Spec-Zone.ru

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