std::move
| Определён в заголовке <algorithm>
|
||
template< class InputIt, class OutputIt >
OutputIt move( InputIt first, InputIt last,
OutputIt d_first );
|
(1) | (начиная с C++11) (constexpr начиная с C++20) |
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 >
ForwardIt2 move( ExecutionPolicy&& policy,
ForwardIt1 first, ForwardIt1 last,
ForwardIt2 d_first );
|
(2) | (начиная с C++17) |
[first, last) в другой диапазон, начиная с d_first, начиная с first и продвигаясь к last. После этой операции элементы в исходном перемещённом диапазоне по-прежнему будут содержать допустимые значения соответствующего типа, но не обязательно те же значения, что и до перемещения.policy.true:
|
|
(до C++20) |
|
|
(начиная с C++20) |
Если d_first находится в диапазоне [first, last), поведение не определено. В этом случае вместо неё можно использовать std::move_backward.
Параметры
| first, last | - | пара итераторов, определяющих исходный диапазон элементов для перемещения |
| d_first | - | начало диапазона назначения |
| policy | - | используемая политика выполнения |
| Требования к типам | ||
-InputIt должен соответствовать требованиям LegacyInputIterator.
| ||
-OutputIt должен соответствовать требованиям LegacyOutputIterator.
| ||
-ForwardIt1, ForwardIt2 должен соответствовать требованиям LegacyForwardIterator.
| ||
Возвращаемое значение
Итератор на элемент, следующий за последним перемещённым элементом.
Сложность
Ровно std::distance(first, last) присваиваний перемещением.
Исключения
Перегрузка с параметром шаблона с именем ExecutionPolicy сообщает об ошибках следующим образом:
- Если выполнение функции, вызванной в рамках алгоритма, выбрасывает исключение и
ExecutionPolicyявляется одной из стандартных политик, вызывается std::terminate. Для любого другогоExecutionPolicyповедение определяется реализацией. - Если алгоритму не удаётся выделить память, выбрасывается std::bad_alloc.
Возможная реализация
template<class InputIt, class OutputIt>
OutputIt move(InputIt first, InputIt last, OutputIt d_first)
{
for (; first != last; ++d_first, ++first)
*d_first = std::move(*first);
return d_first;
}
|
Примечания
При перемещении перекрывающихся диапазонов std::move подходит при перемещении влево (начало диапазона назначения находится за пределами исходного диапазона), в то время как std::move_backward подходит при перемещении вправо (конец диапазона назначения находится за пределами исходного диапазона).
Пример
Следующий код перемещает объекты потоков (которые сами по себе не копируемы) из одного контейнера в другой.
#include <algorithm>
#include <chrono>
#include <iostream>
#include <iterator>
#include <list>
#include <thread>
#include <vector>
void f(int n)
{
std::this_thread::sleep_for(std::chrono::seconds(n));
std::cout << "thread " << n << " ended" << std::endl;
}
int main()
{
std::vector<std::jthread> v;
v.emplace_back(f, 1);
v.emplace_back(f, 2);
v.emplace_back(f, 3);
std::list<std::jthread> l;
// copy() would not compile, because std::jthread is noncopyable
std::move(v.begin(), v.end(), std::back_inserter(l));
}
Вывод:
thread 1 ended
thread 2 ended
thread 3 ended
См. также
(C++11) |
перемещает диапазон элементов в новое место в обратном порядке (шаблон функции & функциональный объект алгоритма) |
(C++20) |
|
(C++11) |
преобразует аргумент в xvalue (шаблон функции) |
(C++20) |
перемещает диапазон элементов в новое место (функциональный объект алгоритма) |