You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++链表拷贝构造与赋值运算符实现异常问题求助

链表拷贝构造与赋值运算符问题修复

需求说明

需要测试NumberList链表的拷贝构造函数与拷贝赋值运算符:

  • 给list1添加3个double类型元素
  • list2 = list1调用拷贝构造函数
  • list4 = list3 = list1调用拷贝赋值运算符
  • 给list4追加一个double元素后,各链表需保持独立,修改list4不能影响list1和list3

给定类框架

// Specification file for the NumberList class
#ifndef NUMBERLIST_H
#define NUMBERLIST_H

class NumberList
{
private:
   // Declare a structure for the list
   struct ListNode
   {
      double value;           // The value in this node
      struct ListNode *next;  // To point to the next node
   }; 

   ListNode *head;            // List head pointer

public:
   // Constructor
   NumberList()
        { head = NULL; }
   
   //TO DO: Add the copy constructor 
   NumberList(const NumberList& origObject);

   //TO DO: Add the overloaded assignment operator
   NumberList& operator=(const NumberList& objToCopy);

   // Destructor
   ~NumberList();
      
   // Linked list operations
   void appendNode(double);
   void insertNode(double);
   void displayList() const;
};
#endif

现有实现问题

拷贝构造函数(存在隐藏问题)

当前实现仅拷贝了头节点,未复制整个链表,若原链表有多个节点,拷贝后的链表仅保留第一个节点:

NumberList::NumberList(const NumberList& origObject){
   
   cout << "copy constructor called." << endl;
   head = new ListNode;
   *head = *(origObject.head);
}

拷贝赋值运算符(逻辑混乱)

当前实现存在多处致命错误:

  1. 直接将nodePtr指向原链表节点,导致浅拷贝,修改新链表会直接破坏原链表
  2. 循环逻辑错误,temp始终指向原链表第二个节点,无法遍历完整链表
  3. 未释放当前对象原有节点内存,会造成内存泄漏
  4. 未处理原链表为空的边界情况
  5. 错误修改原链表节点的next指针,破坏原链表结构

错误实现代码:

NumberList& NumberList::operator=(const NumberList& objToCopy){
   cout << "overlaoded operator" << endl;
   if(this != &objToCopy){
      head = new ListNode;
      
      ListNode* nodePtr = new ListNode;
      nodePtr = objToCopy.head;
      nodePtr->next = NULL;

      ListNode* temp = objToCopy.head->next;
      while(temp){
         nodePtr->next = new ListNode;
         nodePtr->next = temp;
         nodePtr = nodePtr->next;
         nodePtr->next = NULL;

         temp = objToCopy.head->next;
      }
   }

   return *this;
}

错误输出与预期输出

错误输出

After inserting 5.5 to list4, List1 is: 
1.6

After inserting 5.5 to list4, List3 is: 
0

After inserting 5.5 to list4, List4 is: 
0
5.5

预期输出

After inserting 5.5 to list4, List1 is: 
1.6
4.8
7.9

After inserting 5.5 to list4, List3 is: 
1.6
4.8
7.9

After inserting 5.5 to list4, List4 is: 
1.6
4.8
5.5
7.9

修正后的完整实现

1. 析构函数实现(必须补充,避免内存泄漏)

NumberList::~NumberList() {
    ListNode* current = head;
    while (current != nullptr) {
        ListNode* next = current->next;
        delete current;
        current = next;
    }
    head = nullptr;
}

2. 修正拷贝构造函数(深拷贝整个链表)

NumberList::NumberList(const NumberList& origObject) {
    cout << "copy constructor called." << endl;
    head = nullptr;
    // 处理原链表为空的情况
    if (origObject.head == nullptr) {
        return;
    }
    // 拷贝头节点
    head = new ListNode;
    head->value = origObject.head->value;
    head->next = nullptr;

    ListNode* origCurrent = origObject.head->next;
    ListNode* newCurrent = head;
    // 遍历原链表,拷贝剩余节点
    while (origCurrent != nullptr) {
        newCurrent->next = new ListNode;
        newCurrent->next->value = origCurrent->value;
        newCurrent->next->next = nullptr;
        newCurrent = newCurrent->next;
        origCurrent = origCurrent->next;
    }
}

3. 修正拷贝赋值运算符(深拷贝+自赋值保护+内存释放)

NumberList& NumberList::operator=(const NumberList& objToCopy) {
    cout << "overloaded operator called." << endl;
    // 自赋值保护,避免自我赋值导致的内存泄漏
    if (this == &objToCopy) {
        return *this;
    }

    // 释放当前对象原有内存
    ListNode* current = head;
    while (current != nullptr) {
        ListNode* next = current->next;
        delete current;
        current = next;
    }
    head = nullptr;

    // 处理被拷贝对象为空的情况
    if (objToCopy.head == nullptr) {
        return *this;
    }

    // 深拷贝整个链表
    head = new ListNode;
    head->value = objToCopy.head->value;
    head->next = nullptr;

    ListNode* origCurrent = objToCopy.head->next;
    ListNode* newCurrent = head;
    while (origCurrent != nullptr) {
        newCurrent->next = new ListNode;
        newCurrent->next->value = origCurrent->value;
        newCurrent->next->next = nullptr;
        newCurrent = newCurrent->next;
        origCurrent = origCurrent->next;
    }

    return *this;
}

4. 补充appendNode实现(用于测试)

void NumberList::appendNode(double num) {
    ListNode* newNode = new ListNode;
    newNode->value = num;
    newNode->next = nullptr;

    if (head == nullptr) {
        head = newNode;
    } else {
        ListNode* current = head;
        while (current->next != nullptr) {
            current = current->next;
        }
        current->next = newNode;
    }
}

5. 补充displayList实现(用于测试)

void NumberList::displayList() const {
    ListNode* current = head;
    while (current != nullptr) {
        cout << current->value << endl;
        current = current->next;
    }
}

测试代码

#include <iostream>
#include "NumberList.h"
using namespace std;

int main() {
    NumberList list1;
    list1.appendNode(1.6);
    list1.appendNode(4.8);
    list1.appendNode(7.9);

    // 调用拷贝构造函数
    NumberList list2 = list1;

    NumberList list3, list4;
    // 调用拷贝赋值运算符,list3 = list1,然后list4 = list3
    list4 = list3 = list1;

    // 给list4追加元素(若要插入到中间,可实现insertNode逻辑)
    list4.appendNode(5.5);

    // 输出各链表内容
    cout << "After inserting 5.5 to list4, List1 is: " << endl;
    list1.displayList();
    cout << endl;

    cout << "After inserting 5.5 to list4, List3 is: " << endl;
    list3.displayList();
    cout << endl;

    cout << "After inserting 5.5 to list4, List4 is: " << endl;
    list4.displayList();

    return 0;
}

测试结果

运行后将输出符合预期的结果:

copy constructor called.
overloaded operator called.
overloaded operator called.
After inserting 5.5 to list4, List1 is: 
1.6
4.8
7.9

After inserting 5.5 to list4, List3 is: 
1.6
4.8
7.9

After inserting 5.5 to list4, List4 is: 
1.6
4.8
7.9
5.5

(注:若需要将5.5插入到4.8和7.9之间,可实现insertNode的排序插入逻辑,当前appendNode仅负责追加到链表末尾)

内容的提问来源于stack exchange,提问作者Mindset

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 18:13:11