std::move
Определено в заголовке <utility> |
||
|---|---|---|
template< class T > typename std::remove_reference<T>::type&& move( T&& t ) noexcept; |
(с C++11) (до C++14) |
|
template< class T > constexpr std::remove_reference_t<T>&& move( T&& t ) noexcept; |
(с C++14) |
std::move используется для указания, что объект t может быть перемещён, т.е. для эффективной передачи ресурсов от t другому объекту.
В частности, std::move производит выражение xvalue, которое идентифицирует свой аргумент t. Это точно эквивалентно преобразованию в ссылку на rvalue.
Параметры
| t | - | перемещаемый объект |
Возвращаемое значение
static_cast<typename std::remove_reference<T>::type&&>(t)
Примечания
Функции, принимающие параметры ссылок на rvalue (включая конструкторы перемещения, операторы присваивания перемещения и обычные члены, такие как std::vector::push_back) выбираются механизмом разрешения перегрузки при вызове с аргументами rvalue (либо prvalue, например, временный объект, либо xvalue, например, тот, который создаётся std::move). Если аргумент идентифицирует владеющий ресурсами объект, эти перегрузки могут, но не обязаны переместить любые ресурсы, содержащиеся в аргументе. Например, конструктор перемещения связанного списка может скопировать указатель на голову списка и сохранить nullptr в аргументе вместо выделения и копирования отдельных узлов.
Имена переменных типа ссылка на rvalue являются lvalue, и их необходимо преобразовать в xvalue, чтобы они связывались с перегрузками функций, принимающими параметры ссылок на rvalue, поэтому конструкторы перемещения и операторы присваивания перемещения обычно используют std::move.
// Simple move constructor
A(A&& arg) : member(std::move(arg.member)) // the expression "arg.member" is lvalue
{}
// Simple move assignment operator
A& operator=(A&& other)
{
member = std::move(other.member);
return *this;
}Исключением является случай, когда тип параметра функции является ссылкой на rvalue на шаблонный параметр типа ("пересылающая ссылка" или "универсальная ссылка"), в этом случае используется std::forward.
Если не указано иное, все объекты стандартной библиотеки, из которых перемещение выполнено, находятся в «валидном, но неопределённом состоянии», что означает, что инварианты класса объекта соблюдаются (поэтому функции без предварительных условий, такие как оператор присваивания, могут безопасно использоваться с объектом после перемещения):
std::vector<std::string> v;
std::string str = "example";
v.push_back(std::move(str)); // str is now valid but unspecified
str.back(); // undefined behavior if size() == 0: back() has a precondition !empty()
if (!str.empty())
str.back(); // OK, empty() has no precondition and back() precondition is met
str.clear(); // OK, clear() has no preconditionsКроме того, функции стандартной библиотеки, вызываемые с аргументами xvalue, могут предполагать, что аргумент является единственной ссылкой на объект; если он был создан из lvalue с std::move, проверки на алиасинг не производятся. Тем не менее, самоприсваивание перемещения стандартных типов библиотек гарантирует, что объект находится в валидном (но обычно неопределённом) состоянии:
std::vector<int> v = {2, 3, 3};
v = std::move(v); // the value of v is unspecifiedПример
#include <iomanip>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
int main()
{
std::string str = "Salut";
std::vector<std::string> v;
// uses the push_back(const T&) overload, which means
// we'll incur the cost of copying str
v.push_back(str);
std::cout << "After copy, str is " << std::quoted(str) << '\n';
// uses the rvalue reference push_back(T&&) overload,
// which means no strings will be copied; instead, the contents
// of str will be moved into the vector. This is less
// expensive, but also means str might now be empty.
v.push_back(std::move(str));
std::cout << "After move, str is " << std::quoted(str) << '\n';
std::cout << "The contents of the vector are { " << std::quoted(v[0])
<< ", " << std::quoted(v[1]) << " }\n";
}Возможный вывод:
After copy, str is "Salut"
After move, str is ""
The contents of the vector are { "Salut", "Salut" }См. также
|
(C++11) |
пересылает аргумент функции (шаблон функции) |
|
(C++11) |
получает ссылку на rvalue, если конструктор перемещения не генерирует исключение (шаблон функции) |
|
(C++11) |
перемещает диапазон элементов в новое местоположение (шаблон функции) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/utility/move