C++传递对象引用时类成员指针失效触发SIGSEGV问题求助
咱们先把这个SIGSEGV错误的根源揪出来——悬挂指针(Dangling Pointer),结合你的代码细节,问题出在这几个核心点上:
1. 第二个构造函数的设计缺陷
你的第二个构造函数直接保存了传入Poly对象的地址:
rat::rat(Poly &p1, Poly &p2) : p1(&p1), p2(&p2) { }
如果传入的Poly是临时对象(比如r1*r1+r2这类表达式里生成的临时Poly实例),这些临时对象会在当前表达式执行完后立刻被销毁。这时候你的rat对象里的p1、p2就指向了已经被释放的内存,后续访问(比如operator<<里的解引用操作)自然会触发段错误,你看到的乱码d值就是内存被覆写后的垃圾数据。
2. 忽略了拷贝构造函数的作用
你提到执行rat r = r1*r1+r2;时出问题,这里要注意:=在这里是拷贝构造,不是你写的赋值运算符!编译器会生成默认的拷贝构造函数,默认行为是浅拷贝——直接复制指针值。如果r1*r1+r2返回的是临时rat对象,当这个临时对象销毁时,它持有的p1、p2指向的内存会被释放(假设Poly有正确的析构函数),而r里的指针就会变成悬空指针,后续访问必然出错。你写的赋值运算符根本没被调用,所以解决不了问题。
3. const成员d的误导
你说r.p1->d是const,这只是意味着你无法修改它,但如果指针指向的内存已经失效,即使是const成员也会读取到垃圾值,这和const本身无关,根源还是指针悬空。
步骤1:重构构造函数,改用深拷贝
把第二个构造函数改成深拷贝传入的Poly对象,而不是直接保存外部对象的指针,这样你的rat会拥有独立的Poly实例,不再依赖外部对象的生命周期:
rat::rat(const Poly &p1, const Poly &p2) : p1(new Poly(p1)), p2(new Poly(p2)) { }
步骤2:手动实现拷贝构造函数和析构函数
必须自己写拷贝构造函数(深拷贝)和析构函数,避免编译器生成的默认浅拷贝带来的问题:
// 析构函数:释放p1和p2指向的内存,避免内存泄漏 rat::~rat() { delete p1; delete p2; } // 拷贝构造函数:深拷贝传入对象的Poly实例 rat::rat(const rat &other) : p1(new Poly(*other.p1)), p2(new Poly(*other.p2)) { }
步骤3:完善赋值运算符(用拷贝交换 idiom)
你之前写的赋值运算符可以优化成更安全的拷贝交换方式,避免异常安全问题:
rat& rat::operator=(rat other) { // 传值时自动触发拷贝构造 std::swap(p1, other.p1); std::swap(p2, other.p2); return *this; }
这样当other离开作用域时,原来的p1、p2会被它的析构函数自动释放,既安全又简洁。
步骤4:修改友元operator<<为const引用
打印操作不应该修改rat对象,所以把参数改成const引用,同时确保Poly的operator<<也支持const对象:
ostream &operator<<(ostream &stream, const rat &r) { return stream << *(r.p1) << "--------------------------" << std::endl << *(r.p2); }
如果做完以上步骤还是有问题,建议检查:
Poly类的析构函数是否正确释放了自己的资源(比如动态分配的数组),避免内存泄漏或二次释放。Poly的拷贝构造函数是否正确实现了深拷贝,如果Poly本身有动态成员,浅拷贝会导致同样的悬空问题。
内容的提问来源于stack exchange,提问作者Ben Yaakobi

