std::uninitialized_move
Определён в заголовочном файле <memory> | ||
|---|---|---|
template< class InputIt, class NoThrowForwardIt >
NoThrowForwardIt uninitialized_move( InputIt first, InputIt last,
NoThrowForwardIt d_first );
| (1) |
(начиная с C++17) (constexpr начиная с C++26) |
template< class ExecutionPolicy,
class ForwardIt, class NoThrowForwardIt >
NoThrowForwardIt uninitialized_move( ExecutionPolicy&& policy,
ForwardIt first, ForwardIt last,
NoThrowForwardIt d_first );
| (2) | (начиная с C++17) |
d_first, из элементов исходного диапазона [first, last), как если бы выполнялось for(;first!=last;++d_first,(void)++first)
::new(voidify(*d_first))
typenamestd::iterator_traits<NoThrowForwardIt>::value_type(deref-move(*iter));
returnd_first;
[first, last) остаются в допустимом, но неуказанном состоянии, а уже созданные объекты уничтожаются в неуказанном порядке.policy.true: |
| (до C++20) |
|
| (начиная с C++20) |
| Если | (начиная с C++20) |
Параметры
| first, last | - | пара итераторов, задающих диапазон перемещаемых элементов |
| d_first | - | начало целевого диапазона |
| policy | - | используемая политика выполнения |
| Требования к типам | ||
-InputIt должен удовлетворять требованиям LegacyInputIterator. |
||
-ForwardIt должен удовлетворять требованиям LegacyForwardIterator. |
||
-NoThrowForwardIt должен удовлетворять требованиям LegacyForwardIterator. |
||
-Инкремент, присваивание, сравнение и разыменование допустимых экземпляров NoThrowForwardIt не должны вызывать исключения. |
||
Возвращаемое значение
Как описано выше.
Исключения
2) Во время выполнения:- Если временные ресурсы памяти, необходимые для параллелизации, недоступны, выбрасывается
std::bad_alloc. - Если при доступе к объектам через аргумент алгоритма возникает неперехваченное исключение, поведение определяется политикой выполнения (для стандартных политик вызывается
std::terminate).
Примечания
Если входной итератор разыменовывается в rvalue, поведение std::uninitialized_move совпадает с поведением std::uninitialized_copy.
| Макрос проверки поддержки возможностей | Значение | Стандарт | Возможность |
|---|---|---|---|
__cpp_lib_raw_memory_algorithms | 202411L | (C++26) |
constexpr для специализированных алгоритмов <memory>, (1) |
Возможная реализация
template<class InputIt, class NoThrowForwardIt>
constexpr NoThrowForwardIt uninitialized_move(InputIt first, InputIt last,
NoThrowForwardIt d_first)
{
using ValueType = typename std::iterator_traits<NoThrowForwardIt>::value_type;
auto current = d_first;
try
{
for (; first != last; ++first, (void) ++current)
{
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);
}
return current;
}
catch (...)
{
std::destroy(d_first, current);
throw;
}
}
|
Пример
#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[]{"Home", "Work!"};
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(std::begin(in), std::end(in), 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: "Home" "Work!" after move, in: "" "" after move, out: "Home" "Work!"
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Применён к | Опубликованное поведение | Корректное поведение |
|---|---|---|---|
| LWG 3918 | C++17 | Перемещающее конструирование всегда выполняется, даже если входной итератор разыменовывается в prvalue | в этом случае перемещающее конструирование не выполняется |
См. также
| копирует диапазон объектов в неинициализированную область памяти (шаблон функции и функциональный объект алгоритма) |
|
|
(C++20) | |
|
(C++17) | перемещает заданное количество объектов в неинициализированную область памяти (шаблон функции и функциональный объект алгоритма) |
|
(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