代码实现
#include <iostream>
#include <cstring>
class DynamicArray {
private:
int* data;
size_t size;
public:
// 构造函数
DynamicArray(size_t s) : size(s) {
data = new int[size];
std::memset(data, 0, size * sizeof(int));
}
// 析构函数
~DynamicArray() {
delete[] data;
}
// 拷贝构造函数
DynamicArray(const DynamicArray& other) : size(other.size) {
data = new int[size];
std::memcpy(data, other.data, size * sizeof(int));
}
// 移动构造函数
DynamicArray(DynamicArray&& other) noexcept : size(other.size), data(other.data) {
other.data = nullptr;
other.size = 0;
}
// 拷贝赋值运算符
DynamicArray& operator=(const DynamicArray& other) {
if (this != &other) {
delete[] data;
size = other.size;
data = new int[size];
std::memcpy(data, other.data, size * sizeof(int));
}
return *this;
}
// 移动赋值运算符
DynamicArray& operator=(DynamicArray&& other) noexcept {
if (this != &other) {
delete[] data;
size = other.size;
data = other.data;
other.data = nullptr;
other.size = 0;
}
return *this;
}
};
关键步骤和原理
- 参数声明:移动构造函数的参数是一个右值引用
DynamicArray&& other
,表明这个构造函数处理的是一个即将被销毁的对象。noexcept
关键字表明该函数不会抛出异常,有助于编译器进行优化。
- 资源转移:在移动构造函数中,直接将源对象
other
的资源(data
指针和 size
)转移到新对象。这是通过将 other.data
赋值给新对象的 data
,以及将 other.size
赋值给新对象的 size
来实现的。
- 源对象重置:为了避免源对象在析构时释放已转移的资源(从而导致悬空指针问题),需要将源对象的
data
指针设为 nullptr
,并将 size
设为 0
。这样,当源对象析构时,它不会尝试释放已经不属于它的内存。
- 性能提升:与拷贝构造函数不同,移动构造函数不需要分配新的内存并逐个复制元素,因此在性能上有显著提升,尤其是对于大型数组。它只是简单地转移资源的所有权,这是一种非常高效的操作。