#include <iostream>
#include <memory>
class MyClass {
private:
int* data;
size_t size;
public:
// 构造函数
MyClass(size_t s) : size(s) {
data = new int[s];
for (size_t i = 0; i < s; ++i) {
data[i] = i;
}
}
// 析构函数
~MyClass() {
delete[] data;
}
// 拷贝构造函数
MyClass(const MyClass& other) : size(other.size) {
data = new int[size];
for (size_t i = 0; i < size; ++i) {
data[i] = other.data[i];
}
}
// 拷贝赋值运算符
MyClass& operator=(const MyClass& other) {
if (this != &other) {
delete[] data;
size = other.size;
data = new int[size];
for (size_t i = 0; i < size; ++i) {
data[i] = other.data[i];
}
}
return *this;
}
// 移动构造函数
MyClass(MyClass&& other) noexcept : size(other.size), data(other.data) {
other.size = 0;
other.data = nullptr;
}
// 移动赋值运算符
MyClass& operator=(MyClass&& other) noexcept {
if (this != &other) {
delete[] data;
size = other.size;
data = other.data;
other.size = 0;
other.data = nullptr;
}
return *this;
}
};
int main() {
MyClass a(5);
MyClass b = std::move(a);
return 0;
}
std::move
在此过程中的作用
- 类型转换:
std::move
本质上是将左值转换为右值引用。在 MyClass b = std::move(a);
这行代码中,a
原本是一个左值(可以取地址的对象),std::move(a)
将其转换为右值引用。右值引用允许我们对临时对象进行操作,避免不必要的拷贝。
- 触发移动语义:当
MyClass
的移动构造函数或移动赋值运算符接收右值引用参数时,编译器会优先调用移动构造函数或移动赋值运算符(如果定义了的话)。这使得资源(如动态分配的数组)可以高效地从一个对象转移到另一个对象,而不是进行深拷贝。在移动构造函数和移动赋值运算符中,源对象的资源被“窃取”,源对象被置于一个可析构的有效但不确定的状态(size
设为0,data
设为 nullptr
)。这样可以避免重复分配内存和拷贝数据,提高性能。