std::aligned_storage

来自cppreference.com
< cpp‎ | types
 
 
工具库
通用工具
格式化库 (C++20)
(C++11)
关系运算符 (C++20 中弃用)
整数比较函数
(C++20)(C++20)(C++20)
(C++20)
swap 与类型运算
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
常用词汇类型
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)

初等字符串转换
(C++17)
(C++17)
栈踪
 
类型支持
基本类型
基础类型
定宽整数类型 (C++11)
数值极限
C 数值极限接口
运行时类型信息
类型特性
类型类别
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
类型属性
(C++11)
(C++11)
(C++14)
(C++11)
(C++11)(C++20 前)
(C++11)(C++20 中弃用)
(C++11)
类型特性常量
元函数
(C++17)
常量求值语境
受支持操作
关系与属性查询
类型修改
(C++11)(C++11)(C++11)
类型变换
aligned_storage
(C++11)
(C++11)
(C++11)
(C++17)
(C++11)(C++20 前)(C++17)
 
定义于头文件 <type_traits>
template< std::size_t Len, std::size_t Align = /*default-alignment*/ >
struct aligned_storage;
(C++11 起)

提供嵌套类型 type ,其为平凡的标准布局类型,适于作为任何大小至多为 Len对齐要求Align 的因数的对象的未初始化存储。

Align 的默认值是任何大小至多为 Len 的对象的最强(最大)对齐要求。若不使用默认值,则 Align 对于某类型 T 必须为 alignof(T) 的值,否则行为未定义。

Len == 0 则行为未定义。

是否支持任何扩展对齐是实现定义的。

添加 aligned_storage 的特化的程序行为未定义。

成员类型

名称 定义
type 长度至少为 Len 并拥有对齐要求 Align 的平凡兼标准布局类型

辅助类型

template< std::size_t Len, std::size_t Align = /*default-alignment*/ >
using aligned_storage_t = typename aligned_storage<Len, Align>::type;
(C++14 起)

注解

std::aligned_storage<>::type 所定义的类型能用于创建适合保有给定类型对象的未初始化内存块,可选地对齐严格于其自然对齐要求,例如在缓存或页边界上。

同任何其他未初始化存储,通过使用布置 new 创建对象,并以显式的析构函数调用销毁。

可能的实现

除了默认实参, aligned_storage 能通过 alignas 表达:

template<std::size_t Len, std::size_t Align /* 未实现默认对齐 */>
struct aligned_storage {
    struct type {
        alignas(Align) unsigned char data[Len];
    };
};

示例

原始的静态 vector 类,演示于对齐存储中创建、访问及析构对象

#include <new>
#include <iostream>
#include <type_traits>
#include <string>
 
template<class T, std::size_t N>
class static_vector
{
    // N 个 T 的正确对齐的未初始化存储
    std::aligned_storage_t<sizeof(T), alignof(T)> data[N];
    std::size_t m_size = 0;
 
public:
    // 在对齐的存储中创建对象
    template<typename ...Args> void emplace_back(Args&&... args) 
    {
        if( m_size >= N ) // 可能的错误处理
            throw std::bad_alloc{};
 
        // 用原位 operator new 在对齐的存储中构造值
        ::new(&data[m_size]) T(std::forward<Args>(args)...);
        ++m_size;
    }
 
    // 在对齐的存储中访问对象
    const T& operator[](std::size_t pos) const 
    {
        // 注意:在 P0137R1 中的对象模型更改后需要 std::launder
        return *std::launder(reinterpret_cast<const T*>(&data[pos]));
    }
 
    // 从对齐的存储中销毁对象
    ~static_vector() 
    {
        for(std::size_t pos = 0; pos < m_size; ++pos) {
            // 注意:在 P0137R1 中的对象模型更改后需要 std::launder
            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) 指定该变量的存储应该按指定量对齐
获取类型的对齐要求
(类模板)
定义适于用作所有给定类型的未初始化存储的类型
(类模板)
具有不小于任何基础类型的内存对齐需求的平凡类型
(typedef)
(C++17)
指针优化屏障
(函数模板)