1.移动语义基本概念
通过移动语义,我们可以利用右值引用,将一个对象的资源“移动”到另一个对象中,避免不必要的内存拷贝和分配。
【右值引用】用于表示“可被移动”或“可被窃取”的对象。
int&& x = 1;
相对应的,左值是指在内存中有确定存储地址的表达式
2.资源所有权问题
当一个对象被移动到另一个对象时,它的资源所有权被转移给了新对象,原对象就不能再使用。
3.基本实现形式
移动构造函数和移动赋值运算符
3.1 移动构造函数
一个不完整的类内函数实现如下:
class MyData {
......
// 移动构造函数
MyData(MyData&& other) {
std::cout << "MyData Move Constructor!" << std::endl;
mDataSize = other.mDataSize;
mData = other.mData;
other.mDataSize = 0;
other.mData = nullptr;
}
int* mData;
int mDataSize;
}
int main() {
// 创建一个MyData对象
MyData data(10);
// 移动构造函数
MyData data_move = std::move(data);
return 0;
}
移动构造函数一定要将原先的数据置零否则会出现程序崩溃等问题
3.2 移动赋值运算符
class StringArray {
.....
StringArray& operator=(StringArray&& other) noexcept {
if (this != &other) {
// release the resources of the current object
delete[] m_data;
// move the resources of the other object to the current object
m_size = other.m_size;
m_data = other.m_data;
// reset the other object
other.m_size = 0;
other.m_data = nullptr;
}
return *this;
}
}
int main() {
......
StringArray new_strs;
new_strs = std::move(strs); // 使用移动赋值运算符
// 此时strs中的数据已经被移动到了new_strs中
return 0;
}
区别在于:
移动构造是在创建新对象时,将已经存在的对象的资源“移动”到新对象上;
移动赋值是在已有对象的基础上,将另一个已有对象的资源“移动”到该对象上