std::aligned_storage
From cppreference.com
| ヘッダ <type_traits> で定義 |
||
| template< std::size_t Len, std::size_t Align = /* default-alignment */ > struct aligned_storage; |
(C++11以降) (C++23で非推奨) |
|
ネストされた型typeを提供する。これはTrivialTypeとStandardLayoutTypeを満たし、サイズが最大Lenで、アライメント要件がAlignの約数である任意のオブジェクトの未初期化ストレージとして使用するのに適している。
Alignのデフォルト値は、サイズが最大Lenである任意のオブジェクトに対する最も厳格な(最大)アライメント要件である。デフォルト値が使用されない場合、Alignは、ある型Tに対するalignof(T)の値でなければならず、そうでなければ未定義の動作となる。
Len == 0の場合、動作は未定義である。
拡張アライメントがサポートされているかどうかは、実装定義である。
プログラムがstd::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以降) (C++23で非推奨) |
|
[編集] 備考
std::aligned_storage<>::typeによって定義される型は、特定の型のオブジェクトを保持するのに適した、未初期化のメモリブロックを作成するために使用できる。これは、オブジェクトの自然なアライメント要件よりも厳密に、例えばキャッシュ境界やページ境界にアライメントされる場合がある。
他の未初期化ストレージと同様に、オブジェクトはプレースメントnewを使用して作成され、明示的なデストラクタ呼び出しによって破棄される。
[編集] 可能な実装
デフォルト引数を除けば、aligned_storageはalignasで表現できる。
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) |
変数用のストレージを特定の量でアラインすることを指定します。 (指定子) |
| (C++11) |
型のアライメント要件を取得する (クラステンプレート) |
| (C++17) |
アラインされたメモリを割り当てる (関数) |
| (C++11以降)(C++23で非推奨) |
与えられたすべての型の未初期化ストレージとして使用するのに適した型を定義する (クラステンプレート) |
| (C++11) |
他のどのスカラ型よりも大きいアライメント要件を持つ自明型 (typedef) |
| (C++17) |
ポインタ最適化の障壁 (関数テンプレート) |