代码之家  ›  专栏  ›  技术社区  ›  pb.

C++-链表-复制构造函数

  •  0
  • pb.  · 技术社区  · 6 年前

    我正在尝试实现复制构造函数,我遇到了一个奇怪的问题。 你能指出我做错了什么吗?

    我得到: 双重自由或腐败(out):0x08936a48

    输出错误:

    Constructor called...
    MyList:
    10 --> 20 --> 30 --> 40 --> 
    MyList2:
    10 --> 20 --> 30 --> 40 --> 
    Destructor called...
    

    代码:

    #include <iostream>
    
    template <typename T>
    class SingleLinkedList{
    protected:
        struct Node{
            T data;
            Node * next;
            Node() : next(nullptr) {}
            Node(const T num) : data(num), next(nullptr) {}
        };
    
    private:
        Node * head;
        Node * tail;
    
    public:
        SingleLinkedList();                                             // constructor
        ~SingleLinkedList();                                            // destructor
        SingleLinkedList(const SingleLinkedList &object);               // copy constructor
        SingleLinkedList& operator=(const SingleLinkedList &object);    // copy assignment
    
        void insert(T const& value);
        void displayList(std::ostream& stream = std::cout) const;
    
    template <typename T>
    SingleLinkedList<T>::SingleLinkedList() : head(nullptr), tail(nullptr){
        std::cout << "Constructor called..." << std::endl;
    }
    
    template <typename T>
    SingleLinkedList<T>::~SingleLinkedList(){
        std::cout << "Destructor called..." << std::endl;
        int index = 1;
        Node * temp = nullptr;
        while(head!=nullptr){
            temp = head;
            head = head->next;
            delete temp;
            //std::cout << "Node number: " << index << " destroyed" << std::endl;
            index++;
        }
    }
    
    template <typename T>
    SingleLinkedList<T>::SingleLinkedList(const SingleLinkedList<T> &oldList){
        SingleLinkedList<T> * newList = new SingleLinkedList<T>();
    
        // is it necessary? my constructor by default initializes head and tail with nulls
        head = nullptr;
        tail = nullptr;
    
        Node * temp = nullptr;
        temp = oldList.head;
    
        while(temp!=nullptr){
            newList->insert(temp->data);
            temp = temp->next;
        }
    }
    
    
    template <typename T>
    void SingleLinkedList<T>::insert(T const& value){
        Node * temp = new Node(value);
        //temp->data = value;
        //temp->next = nullptr;
    
    
        if(head==nullptr){
            head = temp;
            tail = temp;
        }
        else{
            tail->next = temp;
            tail = temp;
        }
    }
    
    template <typename T>
    void SingleLinkedList<T>::displayList(std::ostream& stream) const{
        Node * temp = nullptr;
        temp = head;
    
        while(temp!=nullptr){
            stream << temp->data << " --> ";
            temp = temp->next;
        }
        stream << std::endl;
    }
    
    int main(){
    
        SingleLinkedList<int> * myList = new SingleLinkedList<int>();
        SingleLinkedList<int> * myList2 = myList;
    
        myList->insert(10);
        myList->insert(20);
        myList->insert(30);
    
        myList2->insert(40);
    
        std::cout << "MyList:" << std::endl;
        myList->displayList();
    
        std::cout << "MyList2:" << std::endl;
        myList2->displayList();
    
        delete myList;
        delete myList2;
    
        return 0;
    }
    

    我的“算法”: 1.创建新列表。 2.对于旧列表的每个节点,获取数据并将其插入新列表。

    我不明白如何使用两个不同的列表来释放同一部分内存。 我是学生,不是职业选手。我请求你的理解。

    1 回复  |  直到 6 年前
        1
  •  2
  •   bipll    6 年前

    你的副本真奇怪。您不需要向正在构建的列表中添加元素,而是创建一个新列表(为什么?)然后添加元素。之后,只需退出函数。创建的新列表留在堆上无法访问,即泄漏,并且构建的列表仍然为空。

    你能简单点吗 insert 复制列表的元素,而不是在某个 newList 但在这一个?

    双重删除的发生还有另一个原因:在你的 main 你声明了两个指针, myList myList2 ,它们都指向内存中的同一个列表,然后尝试同时删除它们。你可以通过正确构造 myList2 :

        SingleLinkedList<int> * myList2{new SingleLinkedList<int>(*myList)};
    

    但我建议你在你的生活中彻底摆脱指针 主要的 :

        SingleLinkedList<int> myList;
        SingleLinkedList<int> myList2(myList);
    

    (别忘了改变一切 -> 她喜欢 . (下面是下文。)

    这毕竟不是Java,不是每一个生命周期都始于Java new .