std::uninitialized_default_construct_n
From cppreference.com
| ヘッダ <memory> で定義 |
||
template< class NoThrowForwardIt, class Size > NoThrowForwardIt uninitialized_default_construct_n |
(1) | (C++17以降) (C++26 以降 constexpr) |
| template< class ExecutionPolicy, class NoThrowForwardIt, class Size > NoThrowForwardIt uninitialized_default_construct_n |
(2) | (C++17以降) |
1) 未初期化メモリ領域 first
+ [0, count) に、デフォルト初期化によって、あたかも次のようにして、typename std::iterator_traits<NoThrowForwardIt>::value_type 型のオブジェクトを構築します。
for (; count > 0; (void)++first, --count)
::new (voidify(*first))
typename std::iterator_traits<NoThrowForwardIt>::value_type;
return first;
初期化中に例外がスローされた場合、すでに構築されたオブジェクトは未指定の順序で破棄されます。
2) (1) と同じですが、policy に従って実行されます。
このオーバーロードは、以下のすべての条件が満たされた場合にのみオーバーロード解決に参加します。
|
std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> が true です。 |
(C++20まで) |
|
std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> が true です。 |
(C++20以降) |
目次 |
[編集] パラメータ
| first | - | 初期化する要素の範囲の先頭 |
| count | - | 構築する要素の数 |
| policy | - | 使用する 実行ポリシー |
| 型要件 | ||
-NoThrowForwardIt は LegacyForwardIterator の要件を満たす必要があります。 | ||
-有効な NoThrowForwardIt のインスタンスを介したインクリメント、代入、比較、間接参照は例外をスローしてはなりません。 | ||
[編集] 戻り値
上記の通り。
[編集] 計算量
n に対して線形。
[編集] 例外
テンプレートパラメータ ExecutionPolicy を持つオーバーロードは、次のようにエラーを報告します。
- アルゴリズムの一部として呼び出された関数の実行が例外をスローし、
ExecutionPolicyが 標準ポリシー のいずれかである場合、std::terminate が呼び出されます。その他のExecutionPolicyの場合、動作は実装定義です。 - アルゴリズムがメモリの割り当てに失敗した場合、std::bad_alloc がスローされます。
[編集] 注記
| 機能テストマクロ | 値 | 規格 | 機能 |
|---|---|---|---|
__cpp_lib_raw_memory_algorithms |
202411L |
(C++26) | 特殊なメモリアルゴリズムの場合、(1) は constexpr です。 |
[編集] 考えられる実装
template<class NoThrowForwardIt, class Size> constexpr ForwardIt uninitialized_default_construct_n(NoThrowForwardIt first, Size count) { using T = typename std::iterator_traits<NoThrowForwardIt>::value_type; NoThrowForwardIt current = first; try { for (; countn > 0; (void) ++current, --count) ::new (static_cast<void*>(std::addressof(*current))) T; return current; } catch (...) { std::destroy(first, current); throw; } } |
[編集] 例
このコードを実行
#include <cstring> #include <iostream> #include <memory> #include <string> struct S { std::string m{"default value"}; }; int main() { constexpr int n{3}; alignas(alignof(S)) unsigned char mem[n * sizeof(S)]; try { auto first{reinterpret_cast<S*>(mem)}; auto last = std::uninitialized_default_construct_n(first, n); for (auto it{first}; it != last; ++it) std::cout << it->m << '\n'; std::destroy(first, last); } catch(...) { std::cout << "Exception!\n"; } // For scalar types, uninitialized_default_construct_n // generally does not zero-initialize the given uninitialized memory area. int v[]{1, 2, 3, 4}; const int original[]{1, 2, 3, 4}; std::uninitialized_default_construct_n(std::begin(v), std::size(v)); // An attempt to access v might be an undefined behavior, // pending CWG 1997 to be resolved: // for (const int i : v) // std::cout << i << ' '; // The result is unspecified: std::cout << (std::memcmp(v, original, sizeof(v)) == 0 ? "un" : "") << "modified\n"; }
実行結果の例
default value default value default value unmodified
[編集] 不具合報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 3870 | C++20 | このアルゴリズムは、const ストレージ上にオブジェクトを作成する可能性があります。 | 禁止されたままです。 |
[編集] 関連項目
| 範囲で定義された未初期化メモリ領域に、デフォルト初期化によってオブジェクトを構築します (関数テンプレート) | |
| 開始位置と個数で定義された未初期化メモリ領域に、値初期化によってオブジェクトを構築します (関数テンプレート) | |
| 開始位置と個数で定義された未初期化メモリ領域に、デフォルト初期化によってオブジェクトを構築します (アルゴリズム関数オブジェクト) |