Семантика перемещения имеет два задания:
- Указывает, что владение ресурсом (например, выделенной памятью, указателем FILE * или потоком) перешло в другие руки
- Избегайте ненужных копий в вышеуказанных случаях.
Например, допустим, у нас есть вектор:
vector<int> a;
for(int i = 0; i < 10000; i++) {
a.push_back(i);
}
Если я напишу:
vector<int> b = a;
Это делает копию каждого отдельного элемента в a
, поэтому это медленная операция. Однако, если я напишу
vector<int> b = std::move(a);
Ни один из элементов в a
не копируется, и в итоге получается намного быстрее. Однако a
больше не владеет этими элементами. Мы можем продемонстрировать это, используя следующий код:
#include <vector>
#include <iostream>
int main() {
using std::vector;
vector<int> a = {1, 2, 3};
vector<int> b = std::move(a);
if(a.data() == nullptr) // This should be true now
std::cout << "a.data() is null now\n";
if(a.size() == 0)
std::cout << "a.size() is zero now\n";
}
В моей системе, используя gcc и clang, этот код печатает
a.data() is null now
a.size() is zero now
Это применимо, даже если у вас есть класс-оболочка:
#include <vector>
#include <iostream>
template<class T>
class Wrapper {
public:
// Because all the members of Wrapper are public,
// the compiler automatically generates move and copy constructors
T value;
};
int main() {
using std::vector;
Wrapper<vector<int>> a = {{1, 2, 3}};
Wrapper<vector<int>> b = std::move(a);
// Same output as before
if(a.value.data() == nullptr)
std::cout << "a.data() is null now\n";
if(a.value.size() == 0)
std::cout << "a.size() is zero now\n";
}