答案:C++中自定义类需手动实现拷贝构造函数和赋值运算符以实现深拷贝,避免浅拷贝导致的内存问题;拷贝构造函数用于初始化新对象,参数为const引用,需分配新内存复制数据;赋值运算符用于已存在对象,需检查自我赋值并释放旧资源后再复制;遵循三法则,即若需析构函数、拷贝构造或赋值运算符之一,通常三者均需自定义;现代C++推荐使用智能指针等自动管理资源,减少手动实现。

在C++中,自定义类的拷贝构造函数和赋值运算符是为了控制对象的复制行为。当类中包含指针、动态资源或需要深拷贝时,必须手动实现这两个函数,否则编译器生成的默认版本会进行浅拷贝,可能导致内存泄漏或重复释放等问题。
拷贝构造函数的实现
拷贝构造函数用于用一个已存在的对象初始化新对象,其参数是同类对象的const引用。
- 函数名与类名相同,参数为const 类名&
- 必须使用引用传参,避免无限递归
- 实现深拷贝时,需为指针成员分配新内存并复制内容
示例:
class MyString {
char* data;
public:
MyString(const char* str = nullptr) {
if (str) {
data = new char[strlen(str) + 1];
strcpy(data, str);
} else {
data = new char[1];
*data = '\0';
}
}
// 拷贝构造函数
MyString(const MyString& other) {
data = new char[strlen(other.data) + 1];
strcpy(data, other.data);
}
~MyString() {
delete[] data;
}};
赋值运算符的实现
赋值运算符用于将一个对象的值赋给另一个已存在的对象。需要处理自我赋值和资源清理。
立即学习“C++免费学习笔记(深入)”;
- 返回类型应为类名&,支持连续赋值
- 参数为const 类名&
- 先检查是否自我赋值
- 释放原有资源,再分配新资源并复制
示例:
MyString& operator=(const MyString& other) {
if (this == &other) return *this; // 自我赋值检查
delete[] data; // 释放旧内存
data = new char[strlen(other.data) + 1];
strcpy(data, other.data);
return *this;
}
注意规则:三法则(Rule of Three)
如果类需要自定义析构函数、拷贝构造函数或赋值运算符中的任意一个,通常三个都需要自定义。这是因为它们都与资源管理相关。
- 析构函数:释放动态资源
- 拷贝构造函数:创建新对象时复制资源
- 赋值运算符:对象已存在时重新分配资源
现代C++推荐使用智能指针或容器管理资源,可避免手动实现这些函数。
基本上就这些。只要记住:有指针,就要深拷贝;写了一个,很可能三个都要写。不复杂但容易忽略细节。











