types_aligned_storage

types_aligned_storage (정렬된 저장소)

std::aligned_storage는 주어진 크기와 정렬 요구에 맞는 초기화되지 않은 저장소로 사용할 수 있는 타입을 제공해요. C++11에서 도입되었고 C++23에서 비권장(deprecated)되었어요. 이 페이지에서는 멤버 타입, 헬퍼 타입, 사용 예제 등을 살펴볼게요.

출처: cppreference

본문

개요

<type_traits> 헤더에 정의되어 있어요.

정의
template < std::size_t Len, std::size_t Align = /* default-alignment */ > struct aligned_storage; (C++11 이후) (C++23에서 비권장)

중첩 타입 type을 제공하며, 이 타입은 TrivialTypeStandardLayoutType 조건을 만족하고, 크기가 Len 이하이고 정렬 요구가 Align의 약수인 모든 객체를 위한 초기화되지 않은 저장소로 사용하기에 적합해요.

Align의 기본값은 크기가 Len 이하인 모든 객체에 대한 가장 엄격한(가장 큰) 정렬 요구사항이에요. 기본값을 사용하지 않는다면 Align은 어떤 타입 T에 대한 alignof(T)의 값이어야 하며, 그렇지 않으면 동작이 정의되지 않아요.

Len == 0이면 동작이 정의되지 않아요.

확장 정렬이 지원되는지는 구현에 따라 정의돼요.

프로그램이 std::aligned_storage에 특수화를 추가하면 동작이 정의되지 않아요.

멤버 타입

이름 정의
type 크기가 Len 이상이고 정렬 요구가 Align인 trivial 및 standard-layout 타입

헬퍼 타입

템플릿 별칭
template < std::size_t Len, std::size_t Align = /* default-alignment */ > using aligned_storage_t = typename aligned_storage<Len, Align>::type; (C++14 이후) (C++23에서 비권장)

참고 사항

std::aligned_storage<>::type이 정의하는 타입은 주어진 타입의 객체를 담기에 적합한 초기화되지 않은 메모리 블록을 만드는 데 사용할 수 있어요. 선택적으로 자연 정렬 요구보다 더 엄격하게 정렬할 수도 있는데, 예를 들어 캐시나 페이지 경계에 맞출 수 있어요.

다른 초기화되지 않은 저장소와 마찬가지로, 객체는 배치 new(placement new)를 사용해 생성되고 명시적인 소멸자 호출로 파괴돼요.

가능한 구현

기본 인자를 제외하면 aligned_storagealignas를 사용해 표현할 수 있어요.

template<std::size_t Len, std::size_t Align = /* default alignment not implemented */>
struct aligned_storage
{
    struct type
    {
        alignas(Align) unsigned char data[Len];
    };
};

예제

정렬된 저장소에서 객체의 생성, 접근, 파괴를 보여주는 기본적인 정적 벡터 클래스예요.

#include <cstddef>
#include <iostream>
#include <new>
#include <string>
#include <type_traits>

template<class T, std::size_t N>
class static_vector
{
    // Properly aligned uninitialized storage for N T's
    std::aligned_storage_t<sizeof(T), alignof(T)> data[N];
    std::size_t m_size = 0;

public:
    // Create an object in aligned storage
    template<typename ...Args> void emplace_back(Args&&... args)
    {
        if (m_size >= N) // Possible error handling
            throw std::bad_alloc{};

        // Construct value in memory of aligned storage using inplace operator new
        ::new(&data[m_size]) T(std::forward<Args>(args)...);
        ++m_size;
    }

    // Access an object in aligned storage
    const T& operator[](std::size_t pos) const
    {
        // Note: std::launder is needed after the change of object model in P0137R1
        return *std::launder(reinterpret_cast<const T*>(&data[pos]));
    }

    // Destroy objects from aligned storage
    ~static_vector()
    {
        for (std::size_t pos = 0; pos < m_size; ++pos)
            // Note: std::launder is needed after the change of object model in P0137R1
            std::destroy_at(std::launder(reinterpret_cast<T*>(&data[pos])));
    }
};

int main()
{
    static_vector<std::string, 10> v1;
    v1.emplace_back(5, '*');
    v1.emplace_back(10, '*');
    std::cout << v1[0] << '\n' << v1[1] << '\n';
}

출력:

*****
**********

같이 보기

alignas (C++11) 변수의 저장 공간을 특정 양만큼 정렬하도록 지정해요 (지시자) [edit]
alignment_of (C++11) 타입의 정렬 요구사항을 얻어요 (클래스 템플릿) [edit]
aligned_alloc (C++17) 정렬된 메모리를 할당해요 (함수) [edit]
aligned_union (C++11 이후) (C++23에서 비권장) 주어진 모든 타입을 위한 초기화되지 않은 저장소로 사용하기에 적합한 타입을 정의해요 (클래스 템플릿) [edit]
max_align_t (C++11) 다른 모든 스칼라 타입만큼 큰 정렬 요구를 가진 trivial 타입 (typedef) [edit]
launder (C++17) 포인터 최적화 장벽 (함수 템플릿) [edit]

더 알아보기 (Learn more)

cppreference