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

std::move

Материал из cppreference.com
 
 
Библиотека утилит
Языковая поддержка
Поддержка типов (базовые типы, 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++14)
(C++11)
(C++11)
(C++11)
(C++17)
Общие лексические типы
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)
Элементарные преобразования строк
(C++17)
(C++17)
 
<tbody> </tbody> <tbody class="t-dcl-rev "> </tbody><tbody> </tbody>
Определено в заголовочном файле <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. Это в точности эквивалентно static_cast ссылочного типа 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:

// Простой конструктор перемещения
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)
перемещает диапазон элементов в новое место
(шаблон функции) [править]