What is the purpose of std::aligned_storage?

You can use std::aligned_storage whenever you wish to decouple memory allocation from object creation.

You claim:

Also it is usable only with POD types.

But this is not true. There is nothing preventing std::aligned_storage from being used with non-POD types.

The example on cppreference provides a legitimate use case:

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

The idea here is that once the static_vector is constructed, memory is immediately allocated for N objects of type T, but no objects of type T are created yet.

You cannot do that with a simple T data[N]; array member, because this would immediately run T's constructor for each element, or wouldn't even compile if T is not default-constructible.


First, #pragma directives are not portable. The Standard doesn't define any mandatory pragmas that must be supported, so every compiler is free to define its own set. But std::aligned_storage is required to simply work no matter what compiler you're using. The compiler library writers might define it in terms of pragmas, attributes, or compiler extensions, but a user can just #include <type_traits> and start using it.

And it's not true that "it is usable only with POD types". In fact, one common way of using aligned_storage is as a chunk of memory where other objects of any type can be manually created and destroyed. It or something like it can be used to implement things like std::optional and std::variant.

To show the idea behind this, here's the start of writing a class similar to std::optional:

#include <type_traits>
#include <memory>

template <typename T>
class my_optional
{
private:
    std::aligned_storage_t<sizeof(T), alignof(T)> m_storage;
    bool m_valid;
public:
    constexpr my_optional() noexcept : m_valid(false) {}
    constexpr my_optional(const T& obj)
        noexcept(std::is_nothrow_copy_constructible<T>::value)
        : m_valid(false)
    {
        new(static_cast<void*>(&m_storage)) T(obj);
        m_valid = true;
    }
    constexpr const T& operator*() const
    {
        return *static_cast<const T*>(static_cast<const void*>(&m_storage));
    }
    constexpr T& operator*()
    {
        return *static_cast<T*>(static_cast<void*>(&m_storage));
    }
    ~my_optional()
    {
        if (m_valid)
            operator*().~T();
    }
    // Much more, to obey the Rule Of Five and add more functionality...
 };

std::aligned_storage manages aligned storage. Whether you place POD or non-POD objects in the storage is irrelevant.

The purpose of std::aligned_storage is that it provides a standardized higher-level utility for managing aligned storage, so that you can write cleaner code with less hassles.

Tags:

C++

C++11

Std