1. 定义 MyClass
类
#include <iostream>
#include <cstring>
class MyClass {
private:
int* data;
int size;
public:
// 构造函数
MyClass(int s) : size(s) {
data = new int[size];
for (int i = 0; i < size; ++i) {
data[i] = 0;
}
}
// 析构函数
~MyClass() {
delete[] data;
}
// 拷贝构造函数
MyClass(const MyClass& other) : size(other.size) {
data = new int[size];
std::memcpy(data, other.data, size * sizeof(int));
}
// 赋值运算符重载
MyClass& operator=(const MyClass& other) {
if (this == &other) {
return *this;
}
delete[] data;
size = other.size;
data = new int[size];
std::memcpy(data, other.data, size * sizeof(int));
return *this;
}
};
2. 关键要点
- 拷贝构造函数:
- 分配新的内存空间,大小与源对象相同,即
data = new int[size];
。
- 使用
std::memcpy
或循环逐个复制元素,将源对象的数据成员 data
中的内容复制到新分配的内存中。这里使用 std::memcpy(data, other.data, size * sizeof(int));
。
- 赋值运算符重载:
- 首先检查自我赋值情况,即
if (this == &other)
。如果是自我赋值,直接返回当前对象 return *this;
。
- 释放当前对象已分配的内存
delete[] data;
。
- 分配新的内存空间,并设置大小
size = other.size; data = new int[size];
。
- 复制源对象的数据到新分配的内存中
std::memcpy(data, other.data, size * sizeof(int));
。
- 返回当前对象引用
return *this;
,以支持链式赋值。
3. 可能出现的错误
- 内存泄漏:
- 在赋值运算符重载中,如果忘记释放当前对象已分配的内存
delete[] data;
,会导致内存泄漏,因为新的内存分配后,旧的内存就无法再访问和释放了。
- 未处理自我赋值:
- 如果在赋值运算符重载中没有检查自我赋值情况,直接释放内存并重新分配,会导致在自我赋值时对象的数据被破坏,因为释放内存后再从同一个对象复制数据就会出错。
- 浅拷贝问题:
- 如果拷贝构造函数或赋值运算符重载只是简单地复制指针,而不是分配新内存并复制数据,就会出现浅拷贝问题。多个对象将共享同一块内存,当一个对象析构释放内存后,其他对象的指针就会成为野指针,访问这些野指针会导致未定义行为。