含指针的C++类链式调用get()触发运行时错误,如何基于指针修复?
问题分析与修复方案
这个问题的根源其实是对拷贝构造函数的误用,咱们一步步拆解并解决:
问题核心原因
当你调用v.get().get()时,第一个get()会返回一个临时的X对象,接着对这个临时对象调用get(),此时在get()函数里创建ret对象会触发拷贝构造函数。原拷贝构造函数一开始就执行delete[] ptr;,但此时正在被构造的新对象(ret)的ptr成员是未初始化的野指针(VS环境下用0xcccccccc标记未初始化的栈内存),直接delete一个未初始化的指针必然触发运行时错误。
另外原类还有个隐藏问题:没有定义析构函数,用new[]分配的内存永远不会被释放,会造成内存泄漏。
基于指针的修复实现
我们需要遵循C++的三法则(Rule of Three):当类自定义了析构函数、拷贝构造函数其中一个时,必须同时定义另外两个。下面是修复后的完整代码:
class X { private: int *ptr; public: // 默认构造函数 X() { ptr = new int[2]; ptr[0] = 0; ptr[1] = 0; } // 带参数的构造函数 X(int a, int b) { ptr = new int[2]; ptr[0] = a; ptr[1] = b; } // 修正后的拷贝构造函数:无需提前delete,新对象的ptr还未分配内存 X(const X &val) { ptr = new int[2]; // 先为新对象分配内存 ptr[0] = val.ptr[0]; // 拷贝源对象的值 ptr[1] = val.ptr[1]; } // 添加析构函数,释放动态分配的内存 ~X() { delete[] ptr; ptr = nullptr; // 置空指针,避免后续误操作野指针 } // 重载赋值运算符(三法则要求),处理对象间赋值逻辑 X& operator=(const X &val) { if (this == &val) { // 自我赋值检查,防止释放自身内存后拷贝失败 return *this; } delete[] ptr; // 释放当前对象的旧内存 ptr = new int[2]; // 分配新内存 ptr[0] = val.ptr[0]; // 拷贝值 ptr[1] = val.ptr[1]; return *this; } X get() { X ret(ptr[0], ptr[1]); return ret; } };
关键修复点说明
- 修正拷贝构造函数:去掉了错误的
delete[] ptr;,因为拷贝构造是创建全新对象,此时对象的ptr还未初始化,根本不需要释放内存,直接分配新内存并拷贝值即可。 - 添加析构函数:负责释放
new[]分配的数组内存,避免内存泄漏,同时将指针置空防止野指针问题。 - 重载赋值运算符:处理对象间的赋值操作,先做自我赋值检查,再释放旧内存、分配新内存并拷贝值,最后返回自身引用,避免浅拷贝导致的重复释放问题。
修复后,v.get().get()就能正常运行,同时解决了内存泄漏的潜在问题。
内容的提问来源于stack exchange,提问作者square1001
相关产品推荐
相关产品推荐

