Пространства имён
Варианты
Действия

std::move

Материал из cppreference.com
< cpp‎ | utility
 
 
Библиотека утилит
Языковая поддержка
Поддержка типов (базовые типы, RTTI)
Макросы тестирования функциональности библиотеки (C++20)    
Управление динамической памятью
Программные утилиты
Поддержка сопрограмм(C++20)
Вариативные функции
Трёхстороннее сравнение (C++20)
(C++20)
(C++20)(C++20)(C++20)(C++20)(C++20)(C++20)
Общие утилиты
Дата и время
Функциональные объекты
Библиотека форматирования(C++20)
(C++11)
Операторы отношения (устарело в C++20)
Целочисленные функции сравнения
(C++20)(C++20)(C++20)    
(C++20)
Операции обмена и типа
(C++11)
move
(C++11)
(C++17)
Общие лексические типы
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)
Элементарные преобразования строк
(C++17)
(C++17)
 
Определено в заголовочном файле <utility>
template<class T >
typenamestd::remove_reference<T>::type&& move( T&& t )noexcept;
(начиная с C++11)
(до C++14)
template<class T >
constexprstd::remove_reference_t<T>&& move( T&& t )noexcept;
(начиная с C++14)

std::move используется для указания того, что объект t может быть "перемещён из", т.е. позволяет эффективно передавать ресурсы из t в другой объект.

В частности, std::move создаёт выражение xvalue, которое идентифицирует его аргумент t. Это в точности эквивалентно static_cast ссылочного типа rvalue.

Содержание

[править]Параметры

t объект, который нужно переместить

[править]Возвращаемое значение

static_cast<typenamestd::remove_reference<T>::type&&>(t)

[править]Примечание

Функции, которые принимают ссылочные параметры rvalue (включая конструкторы перемещения, операторы присваивания перемещением и обычные функции-элементы, такие как std::vector::push_back) выбираются разрешением перегрузки, когда вызываются с аргументами rvalue (либо значениями prvalue такими как временный объект, либо значениями xvalue, такими как созданные std::move). Если аргумент идентифицирует объект, владеющий ресурсами, эти перегрузки могут, но не обязательно, перемещать любые ресурсы, удерживаемые аргументом. Например, конструктор перемещения связанного списка может скопировать указатель на начало списка и сохранить nullptr в аргументе вместо выделения и копирования отдельных узлов.

Имена ссылочных переменных rvalue являются значениями lvalue и должны быть преобразованы в значения xvalue для привязки к перегрузкам функций, которые принимают ссылочные параметры rvalue, поэтому конструкторы перемещения и операторы присваивания перемещением обычно используют std::move:

// Простой конструктор перемещения A(A&& arg): member(std::move(arg.member))// выражение "arg.member" равно lvalue{}// Простой оператор присваивания перемещением A& operator=(A&& other){ member = std::move(other.member);return*this;}

Единственным исключением является случай, когда тип параметра функции является ссылкой rvalue на параметр шаблона типа ("пересылаемая ссылка" или "универсальная ссылка"), и в этом случае вместо этого используется std::forward.

Если не указано иное, все объекты стандартной библиотеки, из которых было перемещение, помещаются в "допустимое, но неопределённое состояние", что означает сохранение инвариантов объекта класса (поэтому функции без предварительных условий, такие как оператор присваивания, можно безопасно использовать с объектом после перемещения):

std::vector<std::string> v;std::string str ="пример"; v.push_back(std::move(str));// str теперь действителен, но не определён str.back();// неопределённое поведение, если size() == 0:// back() имеет предварительное условие !empty()if(!str.empty()) str.back();// OK, у empty() нет предусловия, а предусловие back() выполнено   str.clear();// OK, у clear() нет предусловий

Кроме того, стандартные библиотечные функции, вызываемые с аргументами xvalue, могут предполагать, что аргумент является единственной ссылкой на объект; если он был создан из lvalue с помощью std::move, проверки псевдонимов не выполняются. Однако самоприсваивание перемещением типов стандартных библиотек гарантированно переводит объект в допустимое (но обычно неопределённое) состояние:

std::vector<int> v ={2, 3, 3}; v = std::move(v);// значение v не указано

[править]Пример

#include <iomanip>#include <iostream>#include <string>#include <utility>#include <vector>   int main(){std::string str ="Салют";std::vector<std::string> v;   // использует перегрузку push_back(const T&), что означает, // что мы понесём затраты на копирование str v.push_back(str);std::cout<<"После копирования str равен "<<std::quoted(str)<<'\n';   // использует перегрузку push_back(T&&) со ссылкой на rvalue,// что означает, что строки не будут скопированы; вместо// этого содержимое str будет перемещено в вектор. Это дешевле,// но также означает, что str теперь может быть пустым. v.push_back(std::move(str));std::cout<<"После перемещения str равен "<<std::quoted(str)<<'\n';   std::cout<<"Содержимое вектора равно { "<<std::quoted(v[0])<<", "<<std::quoted(v[1])<<" }\n";}

Возможный вывод:

После копирования str равен "Салют" После перемещения str равен "" Содержимое вектора равно { "Салют", "Салют" }

[править]Смотрите также

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