std::uninitialized_move_n
Определено в заголовочном файле <memory> | ||
|---|---|---|
template< class InputIt, class Size, class NoThrowForwardIt >
std::pair<InputIt, NoThrowForwardIt>
uninitialized_move_n( InputIt first, Size count,
NoThrowForwardIt d_first );
| (1) |
(начиная с C++17) (constexpr начиная с C++26) |
template< class ExecutionPolicy,
class ForwardIt, class Size, class NoThrowForwardIt >
std::pair<ForwardIt, NoThrowForwardIt>
uninitialized_move_n( ExecutionPolicy&& policy, ForwardIt first,
Size count, NoThrowForwardIt d_first );
| (2) | (начиная с C++17) |
d_first, из первых count элементов исходного диапазона, начинающегося с first, как если бы выполнялось for(;count>0;++d_first,(void)++first,--count)
::new(voidify(*d_first))
typenamestd::iterator_traits<NoThrowForwardIt>::value_type(deref-move(*iter));
return{first,d_first};
first + [0, count) остаются в корректном, но неуточнённом состоянии, а уже сконструированные объекты уничтожаются в неуточнённом порядке.policy.true: |
| (до C++20) |
|
| (начиная с C++20) |
| Если | (начиная с C++20) |
Параметры
| first | - | начало диапазона перемещаемых элементов |
| d_first | - | начало целевого диапазона |
| count | - | количество перемещаемых элементов |
| policy | - | используемая политика выполнения |
| Требования к типам | ||
-InputIt должен удовлетворять требованиям LegacyInputIterator. |
||
-ForwardIt должен удовлетворять требованиям LegacyForwardIterator. |
||
-NoThrowForwardIt должен удовлетворять требованиям LegacyForwardIterator. |
||
-Инкремент, присваивание, сравнение и разыменование корректных экземпляров NoThrowForwardIt не должны вызывать исключений. |
||
Возвращаемое значение
Как описано выше.
Исключения
2) Во время выполнения:- Если временные ресурсы памяти, необходимые для распараллеливания, недоступны, выбрасывается
std::bad_alloc. - Если при доступе к объектам через аргумент алгоритма возникает неперехваченное исключение, поведение определяется политикой выполнения (для стандартных политик вызывается
std::terminate).
Примечания
Если входной итератор разыменовывается в rvalue, поведение std::uninitialized_move_n совпадает с поведением std::uninitialized_copy_n.
| Макрос проверки поддержки возможностей | Значение | Стандарт | Возможность |
|---|---|---|---|
__cpp_lib_raw_memory_algorithms | 202411L | (C++26) |
constexpr для специализированных алгоритмов <memory>, (1) |
Возможная реализация
template<class InputIt, class Size, class NoThrowForwardIt>
constexpr std::pair<InputIt, NoThrowForwardIt>
uninitialized_move_n(InputIt first, Size count, NoThrowForwardIt d_first)
{
using ValueType = typename std::iterator_traits<NoThrowForwardIt>::value_type;
NoThrowForwardIt current = d_first;
try
{
for (; count > 0; ++first, (void) ++current, --count) {
auto addr = static_cast<void*>(std::addressof(*current));
if constexpr (std::is_lvalue_reference_v<decltype(*first)>)
::new (addr) ValueType(std::move(*first));
else
::new (addr) ValueType(*first);
}
}
catch (...)
{
std::destroy(d_first, current);
throw;
}
return {first, current};
}
|
Пример
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <memory>
#include <string>
void print(auto rem, auto first, auto last)
{
for (std::cout << rem; first != last; ++first)
std::cout << std::quoted(*first) << ' ';
std::cout << '\n';
}
int main()
{
std::string in[]{"One", "Definition", "Rule"};
print("initially, in: ", std::begin(in), std::end(in));
if (constexpr auto sz = std::size(in);
void* out = std::aligned_alloc(alignof(std::string), sizeof(std::string) * sz))
{
try
{
auto first{static_cast<std::string*>(out)};
auto last{first + sz};
std::uninitialized_move_n(std::begin(in), sz, first);
print("after move, in: ", std::begin(in), std::end(in));
print("after move, out: ", first, last);
std::destroy(first, last);
}
catch (...)
{
std::cout << "Exception!\n";
}
std::free(out);
}
}
Возможный вывод:
initially, in: "One" "Definition" "Rule" after move, in: "" "" "" after move, out: "One" "Definition" "Rule"
Отчёты об исправлении дефектов
Следующие отчёты об исправлении дефектов, изменяющие поведение, были применены задним числом к ранее опубликованным стандартам C++.
| DR | Применено к | Опубликованное поведение | Корректное поведение |
|---|---|---|---|
| LWG 3918 | C++17 | перемещающее конструирование всегда выполняется, даже если входной итератор разыменовывается в prvalue | в этом случае перемещающее конструирование не выполняется |
См. также
|
(C++17) | перемещает диапазон объектов в неинициализированную область памяти (шаблон функции и функциональный объект алгоритма) |
|
(C++20) | |
|
(C++11) | копирует заданное количество объектов в неинициализированную область памяти (шаблон функции и функциональный объект алгоритма) |
|
(C++20) | |
|
(C++20) | перемещает заданное количество объектов в неинициализированную область памяти (функциональный объект алгоритма) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/memory/uninitialized_move_n