◐ Shell
clean mode source ↗

std::align — cppreference.com

Материал из cppreference.com

<tbody> </tbody>

Определено в заголовочном файле <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 должен быть основным или поддерживаемым
расширенным значением выравнивания
должен быть только степенью двойки

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