C++自定义Array类popback()无法正确删除末尾元素问题
问题分析与修复方案
核心问题:越界访问的未定义行为
你的popback()函数其实已经正确完成了数组有效长度的缩减(size变为3),但你在main()里错误地访问了index=3、4、6这些超出当前数组有效范围的位置——这些内存要么已经被释放,要么从来不属于当前数组的有效区域,读取到的值是随机的(你看到的7只是原内存未被系统覆盖的巧合),这属于C++中的未定义行为,和delete[]是否完全释放内存无关。
代码中的冗余与风险点
- pushback/popback存在冗余内存操作:创建临时数组后,又重新分配了一次
arry再复制数据,完全可以直接让arry指向临时数组,避免不必要的内存开销。 - 未处理边界情况:当数组size为0时调用
popback(),会执行new int[-1],直接触发运行时错误。 - access函数无边界检查:越界访问不会有任何提示,容易隐藏问题。
- 缺少析构函数:对象销毁时不会释放
arry指向的内存,会造成内存泄漏。
修复后的完整代码
#include <iostream> #include <stdexcept> using namespace std; class Array{ private: int *arry; int sizeofarray; public: Array() : sizeofarray(0), arry(new int[0]) {} // 析构函数:防止内存泄漏 ~Array() { delete[] arry; } // 拷贝构造与赋值运算符(Rule of Three),避免浅拷贝问题 Array(const Array& other) : sizeofarray(other.sizeofarray), arry(new int[other.sizeofarray]) { for(int i = 0; i < sizeofarray; ++i) { arry[i] = other.arry[i]; } } Array& operator=(const Array& other) { if(this != &other) { delete[] arry; sizeofarray = other.sizeofarray; arry = new int[sizeofarray]; for(int i = 0; i < sizeofarray; ++i) { arry[i] = other.arry[i]; } } return *this; } int access(int index) { // 添加边界检查,越界抛出异常 if(index < 0 || index >= sizeofarray) { throw out_of_range("Array index out of bounds"); } return arry[index]; } void pushback(int element) { int *temparray = new int[sizeofarray + 1]; for(int i = 0; i < sizeofarray; ++i) { temparray[i] = arry[i]; } temparray[sizeofarray] = element; delete[] arry; arry = temparray; // 直接指向临时数组,无需重新分配 sizeofarray++; } void popback() { // 处理空数组的边界情况 if(sizeofarray == 0) { throw underflow_error("Cannot pop from empty array"); } int *temparray = new int[sizeofarray - 1]; for(int i = 0; i < sizeofarray - 1; ++i) { temparray[i] = arry[i]; } delete[] arry; arry = temparray; // 直接指向临时数组 sizeofarray--; } int sizey() { return sizeofarray; } }; int main(){ Array myfirstvector; myfirstvector.pushback(9); myfirstvector.pushback(2); myfirstvector.pushback(3); myfirstvector.pushback(4); myfirstvector.pushback(7); myfirstvector.popback(); myfirstvector.popback(); // 仅访问有效范围内的元素(0到size-1) cout << myfirstvector.access(0) << " " << myfirstvector.access(1) << " " << myfirstvector.access(2) << endl; cout << "Size of array: " << myfirstvector.sizey() << endl; return 0; }
关键修改说明
- 成员变量私有化:避免外部直接修改
arry和sizeofarray,保证封装性。 - 添加析构函数与Rule of Three:防止内存泄漏,避免浅拷贝导致的重复释放问题。
- 简化pushback/popback逻辑:直接让
arry指向临时数组,去掉冗余的内存分配操作。 - 边界检查:在
access和popback中添加边界判断,越界时抛出异常,便于调试定位问题。 - 修正main函数访问范围:只访问有效索引(0到size-1),符合
vector的使用逻辑——pop_back后,原末尾元素的位置不再属于数组有效范围,不应再访问。
关于vector的pop_back()逻辑对齐
std::vector的pop_back()仅将内部size减一,不会主动释放内存(也不会修改原末尾元素的值),但访问超出size的元素同样是未定义行为。如果想完全对齐vector的逻辑,可以额外维护capacity(容量)变量,只有当size远小于capacity时才缩减内存,不过当前你的实现(每次popback都缩小内存)也是一种合理的设计。
内容的提问来源于stack exchange,提问作者Harinandan N
相关产品推荐
相关产品推荐

