C++ unorderedSet类运算符重载返回栈内存引用报错如何修复?
问题修复方案
问题根源
- 你当前重载的
operator+返回值为const unorderedSet<elemType>&引用类型,但函数内部创建的unSet是栈上局部对象,函数执行完毕后栈内存会被回收,返回的引用指向已销毁的对象,属于悬空引用,这是触发警告和程序崩溃的直接原因。 - 额外注意:你的类包含堆内存指针成员,当前只实现了拷贝构造函数,缺失拷贝赋值运算符重载,
testIntSet3 = testIntSet1 + testIntSet2赋值逻辑会触发默认浅拷贝,导致多个对象指向同一块堆内存,最终析构时出现double free错误。
修复步骤
1. 修改运算符重载的返回值类型
将operator+、operator-的返回值从引用类型改为值类型,不需要返回引用,C++编译器的返回值优化(RVO)会直接在调用方地址构造返回对象,不会产生额外拷贝开销。
修改类内声明:
// 原声明 // const unorderedSet<elemType>& operator+(const unorderedSet<elemType>&); // const unorderedSet<elemType>& operator-(const unorderedSet<elemType>&); // 修改后 unorderedSet<elemType> operator+(const unorderedSet<elemType>&); unorderedSet<elemType> operator-(const unorderedSet<elemType>&);
2. 修改operator+实现的返回值类型
template <class elemType> // 原返回值为const引用,改为值类型 unorderedSet<elemType> unorderedSet<elemType>::operator+(const unorderedSet<elemType>& otherSet) { unorderedSet<elemType> unSet(this->length + otherSet.length); for (int i = 0; i < this->length; i++) unSet.insertEnd(this->list[i]); for (int i = 0; i < otherSet.length; i++) unSet.insertEnd(otherSet.list[i]); cout << "\n\nunSet:\n"; unSet.print(); return unSet; // 直接返回值即可 }
3. 补充拷贝赋值运算符实现
避免赋值时浅拷贝导致的内存问题,推荐使用复制交换法实现,安全且易维护:
template <class elemType> unorderedSet<elemType>& unorderedSet<elemType>::operator=(unorderedSet<elemType> otherSet) { std::swap(this->maxSize, otherSet.maxSize); std::swap(this->length, otherSet.length); std::swap(this->set, otherSet.set); return *this; }
关于malloc/calloc的说明
不需要使用malloc/calloc,这两个是C语言的内存分配函数,只会分配原始内存不会调用类的构造函数,你的类unorderedSet有自定义构造函数,用new分配内存是符合C++规范的正确方案,当前问题和内存分配方式无关,不需要修改这部分逻辑。
内容的提问来源于stack exchange,提问作者imt
相关产品推荐
相关产品推荐

