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

Posted

技术标签:

【中文标题】C++ - 链表 - 复制构造函数【英文标题】:C++ - linked list - copy constructor 【发布时间】:2018-05-18 13:27:14 【问题描述】:

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

我得到: 双重释放或损坏(输出):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. 为旧链表的每个节点获取数据并插入到新链表中。

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

【问题讨论】:

复制构造函数应该初始化thisnew 一个新实例是不正确的。在这里你创建一个newList,用元素填充它,然后丢弃/泄漏它。 复制构造函数的工作方式与普通构造函数类似。你的对象已经在这里了,你不用new创建它。但这不应该在这里导致段错误,因为您复制了空对象(因此永远不会进入循环)。 谢谢。我误解了一些概念。 【参考方案1】:

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

你能简单地将insert 复制列表的元素,而不是在某个newList 中,而是在这个中吗?

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

    SingleLinkedList<int> * myList2new SingleLinkedList<int>(*myList);

但我建议你完全摆脱 main 中的指针:

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

(之后不要忘记将下面的所有-&gt;s 更改为.s。)

这毕竟不是 Java,不是每个生命周期都以 new 开头。

【讨论】:

非常感谢您的精彩解释。当然,在函数中创建新对象是不必要的,我误解了一些概念。 希望您现在能更好地理解它。 :)

以上是关于C++ - 链表 - 复制构造函数的主要内容,如果未能解决你的问题,请参考以下文章

c++中的双向链表写法,主要实现(增删查改,链表逆置,构造函数,运算符重载,等)

C++中复制构造函数被调用的三种情况

C++链表移动赋值和移动构造函数

C++——构造函数析构函数以及复制构造函数

C++复制构造函数和=号重载问题

C++构造函数详解(复制构造函数)