模板List类+运算符重载异常及拷贝构造、赋值运算符实现咨询
首先,你的程序执行std::cout << l3时出现乱码和异常,核心问题集中在赋值运算符实现错误以及缺少正确的拷贝构造函数导致浅拷贝问题。你的operator+逻辑本身没问题,但拷贝与赋值的漏洞最终引发了异常。
1. 修复完全错误的赋值运算符
你当前的赋值运算符完全不符合C++规范:它没有修改当前对象(*this),反而创建新对象返回,而且循环里的n = n->value是致命错误——这相当于把节点值当成指针使用,直接导致非法内存访问。
正确的赋值运算符需要完成这些操作:
- 先清空当前对象的所有节点(避免内存泄漏)
- 遍历传入的列表,将每个元素添加到当前对象
- 返回
*this以支持链式赋值(比如l1 = l2 = l3)
修复后的代码:
List<T>& operator=(const List<T>& secList) { // 第一步:清空当前对象已有节点 Node* current = head; while (current != nullptr) { Node* next = current->next; delete current; current = next; } head = tail = nullptr; sizeList = 0; // 第二步:复制secList的元素到当前对象 Node* n = secList.head; while (n != nullptr) { add(n->value); n = n->next; } return *this; }
注意参数用const List<T>&(避免不必要的拷贝),返回值用List<T>&(返回当前对象的引用)。
2. 实现正确的拷贝构造函数
因为你没有自定义拷贝构造函数,编译器会生成默认的浅拷贝构造函数——它只会简单复制head、tail、sizeList等成员变量,不会复制链表节点。这会导致多个List对象共享同一段链表内存,当其中一个对象被销毁(比如operator+返回的临时对象),析构函数会释放这段内存,剩下的对象(比如l3)的head就变成悬空指针,输出时自然乱码或崩溃。
拷贝构造函数的逻辑和赋值运算符类似,只是在对象初始化时完成复制:
List(const List<T>& other) : head(nullptr), tail(nullptr), sizeList(0) { Node* n = other.head; while (n != nullptr) { add(n->value); n = n->next; } }
用初始化列表先把新对象的head、tail、sizeList初始化为空,再遍历other的节点逐个添加到新对象中。
3. 补全析构函数避免内存泄漏
如果你的List类还没有析构函数,一定要补上,否则会造成内存泄漏,配合浅拷贝还会导致重复释放内存:
~List() { Node* current = head; while (current != nullptr) { Node* next = current->next; delete current; current = next; } }
4. operator+的小优化
你的operator+逻辑正确,但可以优化参数为const List<T>&,避免不必要的拷贝:
List<T> operator+(const List<T>& secList) const { List<T> finList; Node* n = this->head; while (n != nullptr) { finList.add(n->value); n = n->next; } Node* p = secList.head; while (p != nullptr) { finList.add(p->value); p = p->next; } return finList; }
加上const修饰符,表示这个运算符不会修改当前对象。
主函数小提醒
你的主函数里连续三次std::cin >> l1;没问题,但要确保operator>>实现正确(你说输出l1正常,所以这部分应该没问题)。
完成以上修复后,l3 = l1 + l2就能正常工作,输出l3也不会出现乱码或崩溃了。
内容的提问来源于stack exchange,提问作者user9664805

