C++自定义MyArray类重载+运算符内存泄漏及输出异常问题如何解决
问题根因分析
垃圾值产生原因
push_end函数存在严重的堆内存越界写入:原数组的申请大小仅为n,你没有做扩容操作直接向a[n]位置写入数据,越界操作会破坏堆结构,后续读取该部分内存时自然会得到未初始化的垃圾值,你观察到的6.93003e-310就是未初始化堆内存的典型表现。- 双参数拷贝构造函数存在变量名冲突:参数
n和类成员变量n重名,导致你传入的拼接总长度参数被覆盖为源数组的长度,数组实际申请内存大小和记录的长度不匹配,访问超出拷贝长度的位置就会读到未初始化值。 operator+重载逻辑完全错误:循环条件用两个数组的总长度遍历第二个数组,直接越界读取第二个数组之外的内存,把垃圾值写入了结果数组,且你完全没有把第一个数组的元素拼接到结果里。
内存泄漏产生原因
push_begin函数申请新的扩容内存后,没有释放旧数组的内存,每次调用都会泄漏对应长度的double数组内存。- 赋值运算符返回值为值类型而非引用,会触发不必要的临时对象拷贝,且未做自赋值检查,存在重复释放、内存泄漏的潜在风险。
修复方案
1. 修复push_end扩容逻辑
void push_end(double last) { auto* temp = new double [n+1]; for (int i = 0; i < n; i++){ temp[i] = a[i]; } temp[n] = last; delete[] a; a = temp; n++; }
2. 修复双参数拷贝构造函数的变量名冲突
MyArray(const MyArray & a2, int new_size) { a = new double[new_size]{}; n = new_size; int copy_len = min(a2.n, new_size); for (int i=0; i< copy_len; i++){ a[i] = a2.a[i]; } }
3. 修复operator+拼接逻辑
friend MyArray operator + (MyArray &arr1, MyArray &arr2){ int n1 = arr1.get_Size(); int n2 = arr2.get_Size(); MyArray ans(n1 + n2); // 拼接第一个数组 for(int i=0; i<n1; i++){ ans.SetA(i, arr1.GetA(i)); } // 拼接第二个数组 for(int i=0; i<n2; i++){ ans.SetA(n1 + i, arr2.GetA(i)); } return ans; }
4. 修复push_begin的内存泄漏
void push_begin(double first) { auto* temp = new double [n+1]; for (int i = 0; i < n; i++){ temp[i+1] = a[i]; } temp[0] = first; delete[] a; // 补充释放旧内存 this->a = temp; n++; }
5. 修复赋值运算符规范
MyArray& operator=(const MyArray& a2) { if (this == &a2) return *this; // 自赋值检查 delete[] a; // 提前释放旧内存 int new_n = a2.n; auto *new_data = new double[new_n]; std::copy_n(a2.a, new_n, new_data); n = new_n; a = new_data; return *this; }
内容的提问来源于stack exchange,提问作者CaliChzHedz
相关产品推荐
相关产品推荐

