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. Оно в точности эквивалентно 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:

// 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)
преобразует аргумент в xvalue, если конструктор перемещения не выбрасывает исключений
(шаблон функции)
move
(C++11)
перемещает диапазон элементов в новое место
(шаблон функции и функциональный объект алгоритма)
ranges::move
(C++20)

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

Spec-Zone.ru

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