1. «Что это?»
Хотя std::move()
технически это функция - я бы сказал, что на самом деле это не функция . Это своего рода конвертер между способами, которыми компилятор учитывает значение выражения.
2. «Что это делает?»
Первое, что нужно отметить, это то, std::move()
что на самом деле ничего не двигается . Он преобразует выражение из lvalue (например, именованной переменной) в xvalue . Значение x сообщает компилятору:
Вы можете разграбить меня, переместить все, что я держу, и использовать это в другом месте (так как я все равно скоро буду уничтожен) ".
другими словами, когда вы используете std::move(x)
, вы позволяете компилятору каннибализировать x
. Таким образом, если x
имеет, скажем, свой собственный буфер в памяти - после std::move()
компиляции он может иметь другой объект, которому он принадлежит.
Вы также можете перейти от значения (например, временного, который вы передаете), но это редко полезно.
3. «Когда его следует использовать?»
Другой способ задать этот вопрос: «Для чего я мог бы уничтожить ресурсы существующего объекта?» хорошо, если вы пишете код приложения, вы, вероятно, не будете много возиться с временными объектами, созданными компилятором. Так что в основном вы бы делали это в таких местах, как конструкторы, операторные методы, функции, аналогичные стандартным библиотечным алгоритмам и т. Д., Где объекты создавались и уничтожались автоматически много. Конечно, это просто правило.
Типичное использование - это «перемещение» ресурсов с одного объекта на другой вместо копирования. @Guillaume ссылается на эту страницу, на которой есть простой короткий пример: замена двух объектов с меньшим количеством копий.
template <class T>
swap(T& a, T& b) {
T tmp(a); // we now have two copies of a
a = b; // we now have two copies of b (+ discarded a copy of a)
b = tmp; // we now have two copies of tmp (+ discarded a copy of b)
}
Использование Move позволяет вам обмениваться ресурсами, а не копировать их:
template <class T>
swap(T& a, T& b) {
T tmp(std::move(a));
a = std::move(b);
b = std::move(tmp);
}
Подумайте о том, что происходит T
, скажем, vector<int>
с размером n. В первой версии вы читаете и записываете 3 * n элементов, во второй версии вы в основном читаете и записываете только 3 указателя на буферы векторов плюс размеры 3 буферов. Конечно, класс T
должен знать, как сделать движение; Ваш класс должен иметь оператор присваивания перемещения и конструктор перемещения для класса, T
чтобы это работало.