在拷贝赋值运算符中使用浅拷贝会存在哪些问题?
浅拷贝数组的核心问题
浅拷贝针对动态分配的数组时,本质只是复制了指向数组首地址的指针,并不会新开辟独立内存复制数组内的全部元素,最终会导致两个对象的数组指针指向同一块堆内存,核心问题有两个:
- 修改其中任意一个对象的数组元素,另一个对象的数组内容也会同步被修改,完全违背了「拷贝后两个对象数据独立」的预期
- 对象生命周期结束触发析构时,同一块堆内存会被两个对象的析构函数先后释放,直接触发*双重释放(double free)*错误,导致程序崩溃
复现问题的代码示例
你可以直接运行下面的C++代码验证崩溃场景:
#include <iostream> class IntArray { public: int* arr; int size; // 构造函数:动态分配数组内存 IntArray(int sz) : size(sz) { arr = new int[size]; } // 采用浅拷贝逻辑的拷贝赋值运算符 IntArray& operator=(const IntArray& src) { if (this == &src) return *this; size = src.size; // 仅复制指针地址,没有新分配内存复制元素,属于浅拷贝 arr = src.arr; return *this; } // 析构函数:释放数组内存 ~IntArray() { delete[] arr; } }; int main() { IntArray arr1(5); arr1.arr[0] = 10; IntArray arr2(3); // 调用浅拷贝赋值运算符 arr2 = arr1; // 现象1:修改arr2的元素,arr1的对应元素也会变化 arr2.arr[0] = 20; std::cout << arr1.arr[0] << std::endl; // 输出为20,不符合拷贝预期 // 现象2:main函数结束时,arr2和arr1先后析构,会连续两次释放同一块内存,触发double free,程序直接崩溃 return 0; }
如果要修复这个问题,只需要把拷贝赋值运算符改成深拷贝逻辑:新开辟一块和源数组大小相同的内存,再把源数组的所有元素逐个复制到新内存中,保证两个对象的数组指针指向不同的内存块即可。
内容的提问来源于stack exchange,提问作者BrandonMoon01
相关产品推荐
相关产品推荐

