- memory[meta header]
- std[meta namespace]
- function template[meta id-type]
- cpp17[meta cpp]
namespace std {
template <class InputIterator, class Size, class ForwardIterator>
pair<InputIterator, ForwardIterator>
uninitialized_move_n(InputIterator first,
Size n,
ForwardIterator result); // (1) C++17
template <class InputIterator, class Size, class ForwardIterator>
constexpr pair<InputIterator, ForwardIterator>
uninitialized_move_n(InputIterator first,
Size n,
ForwardIterator result); // (1) C++26
template <class ExecutionPolicy, class InputIterator, class Size, class ForwardIterator>
pair<InputIterator, ForwardIterator>
uninitialized_move_n(ExecutionPolicy&& exec,
InputIterator first,
Size n,
ForwardIterator result); // (2) C++17
}未初期化領域の範囲のうち先頭N個の要素を配置newで初期化してムーブ出力する。
入力イテレータ範囲[first, first + n)からムーブして未初期化出力イテレータ範囲[result, )に書き込む。
- イテレータ範囲
[result, result + n)が[first, first + n)と重ならないこと
以下と等価:
for (; n > 0; ++result, (void)++first, --n)
::new (static_cast<void*>(addressof(*result)))
typename iterator_traits<ForwardIterator>::value_type(deref-move(first));- deref-move[italic]
ここでderef-move(first)は、*firstが左辺値参照を返す場合はstd::move(*first)、そうでない場合は*firstとなる説明専用のヘルパである。これにより、*firstがprvalueを返すイテレータに対してコピーの省略が保証される。
{first, result}
呼び出すコンストラクタなどから例外が送出された場合、その例外がこの関数の外側に伝播される前に、その時点で構築済のオブジェクトは全て未規定の順序で破棄される。すなわち、例外が送出された場合は初期化対象領域は未初期化のままとなる。
ただし、ムーブ元の範囲[first, first + n)のオブジェクトの一部は、すでにムーブされた結果として有効だが未規定の状態になっていることがある。
#include <iostream>
#include <memory>
#include <vector>
#include <algorithm>
int main()
{
const std::vector<int> v = {1, 2, 3};
std::allocator<int> alloc;
// メモリ確保。
// この段階では、[p, p + size)の領域は未初期化
const std::size_t size = 3;
int* p = alloc.allocate(size);
// 未初期化領域pを初期化しつつ範囲vから要素をムーブ
std::uninitialized_move_n(v.begin(), v.size(), p);
// pの領域が初期化され、かつvからpに要素がコピーされているか確認
std::for_each(p, p + size, [](int x) {
std::cout << x << std::endl;
});
// 要素を破棄
for (std::size_t i = 0; i < size; ++i) {
std::destroy_at(p + i);
}
// メモリ解放
alloc.deallocate(p, size);
}- std::uninitialized_move_n[color ff0000]
- alloc.allocate[link allocator/allocate.md]
- std::destroy_at[link destroy_at.md]
- alloc.deallocate[link allocator/deallocate.md]
1
2
3
- C++17
- Clang: 4.0.1 [mark verified]
- GCC: 7.3 [mark verified]
- Visual C++: ??
- P0040R3 Extending memory management tools
- P3508R0 Wording for "constexpr for specialized memory algorithms"
- C++26から
constexprがついた
- C++26から
- LWG Issue 3054.
uninitialized_copyappears to not be able to meet its exception-safety guarantee- C++20で、例外送出時に「効果なし」とする達成不能な保証が撤廃され、構築済みのオブジェクトを未規定の順序で破棄してから例外を伝播すると明確化された
- LWG Issue 3918.
std::uninitialized_move/_nand guaranteed copy elision- C++26で、要素の構築に説明専用ヘルパ
deref-moveを用いるようになり、*firstがprvalueを返すイテレータに対してコピーの省略が保証されるようになった
- C++26で、要素の構築に説明専用ヘルパ
- LWG Issue 4452. Make deref-move constexpr
- C++26で、この関数が内部で用いる説明専用ヘルパ関数
deref-moveにもconstexprが付き、定数式での評価が可能になった(P3508が見落としていた箇所を補完)
- C++26で、この関数が内部で用いる説明専用ヘルパ関数