C++中基于指针数组实现的栈类赋值运算符重载自赋值异常问题排查求助
问题分析与解决方案
你的赋值运算符没有正确处理自赋值场景,再加上错误的条件判断逻辑,直接导致了自赋值后栈元素变成垃圾值的问题。
为什么会出现垃圾值?
当执行stk = stk时,old是当前对象的引用(也就是同一个对象),我们一步步拆解你的代码执行流程:
- 你通过
if (stack_size != old.stack_size)判断是否释放内存,但自赋值时两者大小完全相等,所以跳过了delete[] array;。 - 拷贝
stack_size和stack_capacity——这两步没实际变化,但本身没问题。 - 执行
array = new int[stack_capacity];:此时array指针指向了一块新的、未初始化的内存。因为old是当前对象的引用,old.array也会同步指向这块新内存! - 最后循环执行
array[i] = old.array[i];:本质是把新数组里的未初始化垃圾值赋值给它自己,最终所有元素都变成了无效值。
另外,你的if (stack_size != old.stack_size)判断完全没有意义:
- 即使两个不同对象的栈大小相等,你也需要释放当前内存(否则会造成内存泄漏)。
- 这个判断不仅无法防止自赋值,反而会在自赋值时触发上述错误。
修复方案
方案1:直接处理自赋值并修正逻辑
修改赋值运算符,先检查是否为自赋值,再正确释放内存:
stack& operator= (const stack& old) { // 自赋值直接返回,不做任何操作 if (this == &old) { return *this; } // 释放当前对象的内存(不管大小是否相等) delete[] array; // 拷贝状态 stack_size = old.stack_size; stack_capacity = old.stack_capacity; // 分配新内存并拷贝元素 array = new int[stack_capacity]; for (size_t i = 0; i < stack_size; ++i) { array[i] = old.array[i]; } return *this; }
方案2:使用Copy-and-Swap Idiom(更推荐)
这种方式不仅能完美处理自赋值,还能提供异常安全性(如果内存分配失败,当前对象的状态不会被破坏)。
首先给stack类添加一个swap成员函数:
void swap(stack& other) noexcept { // 交换所有成员变量 std::swap(array, other.array); std::swap(stack_size, other.stack_size); std::swap(stack_capacity, other.stack_capacity); }
然后简化赋值运算符的实现:
stack& operator= (stack old) { // 传值触发拷贝构造,创建临时对象 swap(old); // 交换当前对象和临时对象的资源 return *this; }
自赋值时,临时对象是当前对象的拷贝,交换后当前对象保持原状态,临时对象会在函数结束时自动销毁,完全不会出现资源错误。
内容的提问来源于stack exchange,提问作者Nurdos
相关产品推荐
相关产品推荐

