Spec-Zone.ru › C++

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" }

См. также

forward
(C++11)
пересылает аргумент функции
(шаблон функции)
move_if_noexcept
(C++11)
получает ссылку на rvalue, если конструктор перемещения не генерирует исключение
(шаблон функции)
move
(C++11)
перемещает диапазон элементов в новое местоположение
(шаблон функции)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/utility/move

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API