1. 浅拷贝问题深度解析与解决方案
1.1 浅拷贝引发的双重释放问题
让我们从一个典型的栈类实现开始分析:
cpp复制class Stack {
public:
Stack(int n = 10) {
_a = (int*)malloc(sizeof(int) * n);
_size = 0;
_capacity = n;
}
~Stack() {
free(_a);
_a = nullptr;
_size = _capacity = 0;
}
private:
int* _a;
size_t _size;
size_t _capacity;
};
当执行以下操作时:
cpp复制Stack st1;
Stack st2(st1); // 这里使用了编译器生成的默认拷贝构造函数
Stack st3(30);
st1 = st3; // 这里使用了编译器生成的默认赋值运算符
这段代码看似简单,实则暗藏两个致命问题:
- 内存泄漏:赋值操作
st1 = st3导致原st1._a指向的内存块丢失,无法被释放 - 双重释放:析构时多个对象指向同一内存块,导致多次释放同一内存区域
提示:在C++中,如果类包含指针成员并管理动态内存,必须自定义拷贝构造函数和赋值运算符,这就是著名的"Rule of Three"原则。
1.2 问题根源与解决方案
浅拷贝问题的本质在于指针成员的简单复制。要解决这个问题,我们需要实现深拷贝:
cpp复制class Stack {
public:
// 深拷贝构造函数
Stack(const Stack& other) {
_a = (int*)malloc(sizeof(int) * other._capacity);
memcpy(_a, other._a, sizeof(int) * other._size);
_size = other._size;
_capacity = other._capacity;
}
// 深拷贝赋值运算符
Stack& operator=(const Stack& other) {
if (this != &other) { // 防止自赋值
int* tmp = (int*)malloc(sizeof(int) * other._capacity);
free(_a); // 释放原有内存
_a = tmp;
memcpy(_a, other._a, sizeof(int) * other._size);
_size = other._size;
