C++ 是否需要删除单链表中动态分配的对象?

C++ 是否需要删除单链表中动态分配的对象?,c++,pointers,linked-list,c++17,singly-linked-list,C++,Pointers,Linked List,C++17,Singly Linked List,我目前正在学习链表,并实现了一个带有Append和Prepend方法的单链表,其中我使用“new”操作符在heap上分配了Node类型的对象。我是否需要使用“delete”取消分配堆上的对象,如果需要,我该怎么做? 这是我的密码:- class List { private: class Node { public: int data; Node* next; Node() { dat

我目前正在学习链表,并实现了一个带有Append和Prepend方法的单链表,其中我使用“new”操作符在heap上分配了Node类型的对象。我是否需要使用“delete”取消分配堆上的对象,如果需要,我该怎么做? 这是我的密码:-

class List
{
private:
    class Node
    {
    public:
        int data;
        Node* next;
        Node()
        {
            data = 0;
            next = NULL;
        }
        Node(const int& data)
        {
            this->data = data;
        }
    };

    Node* head;
public:
    List()
    {
        head = NULL;
    }
    void Append(const int&val);
    void Prepend(const int&val);
    void DisplayAll();
};

void List::Append(const int&val)
{
    Node* n = new Node(val); //dynamically allocated 
    if (head == NULL)
    {
        head = n;
        return;
    }
    Node* temp = NULL;
    temp = head;
    while (temp->next != NULL)
    {
        temp = temp->next;
    }
    temp->next = n;
}

void List::Prepend(const int&val)
{
    Node* node = new Node(val);//dynamically allocated 
    if (head == NULL)
    {
        head = node;
        return;
    }
    node->next = head;
    head = node;
}

void List::DisplayAll()
{
    Node* temp = head;
    while (temp != NULL)
    {
        std::cout << temp->data << ' ';
        temp = temp->next;
    }
}
类列表
{
私人:
类节点
{
公众:
int数据;
节点*下一步;
节点()
{
数据=0;
next=NULL;
}
节点(常量int和数据)
{
这->数据=数据;
}
};
节点*头;
公众:
列表()
{
head=NULL;
}
无效附加(常量int和val);
无效预结束(const int&val);
void DisplayAll();
};
无效列表::追加(常量int&val)
{
Node*n=新节点(val);//动态分配
if(head==NULL)
{
水头=n;
返回;
}
节点*temp=NULL;
温度=水头;
while(临时->下一步!=NULL)
{
温度=温度->下一步;
}
温度->下一步=n;
}
无效列表::前置(常量int&val)
{
Node*Node=new Node(val);//动态分配
if(head==NULL)
{
头部=节点;
返回;
}
节点->下一步=头部;
头部=节点;
}
无效列表::DisplayAll()
{
节点*温度=头部;
while(temp!=NULL)
{
std::cout数据下一步;
}
}

对于初学者,此构造函数

    Node(const int& data)
    {
        this->data = data;
    }
不初始化数据成员
next
。因此,成员函数
Append
Prepend
存在错误

void List::Append(const int&val)
{
    Node* n = new Node(val); //dynamically allocated 
    if (head == NULL)
    {
        head = n;
        return;
    }
    //...

头部节点的数据成员
next
具有不确定的值

您可以像这样简单地声明类
节点

struct Node
{
    int data;
    Node* next;
};

Node* head = nullptr;
例如,在这种情况下,函数
Prepend
如下所示

void List::Prepend( const int &val )
{
    head = new Node { val, head };
}
List() = default;
构造函数看起来像

void List::Prepend( const int &val )
{
    head = new Node { val, head };
}
List() = default;
要释放列表中所有分配的节点,您可以编写另外两个成员函数
clear
,以及调用函数
clear
的析构函数

比如说

#include <functional>

//...

class List
{
//...
public:
    void clear()
    {
        while ( head ) delete std::exchange( head, head->next );
    }

    ~List() { clear(); }
    //...
#包括
//...
班级名单
{
//...
公众:
无效清除()
{
while(head)删除std::exchange(head,head->next);
}
~List(){clear();}
//...

另外,您至少应该编写一个复制构造函数和复制赋值运算符,或者将它们定义为已删除。

如果不再需要,则需要将任何动态分配的数据
删除
d,否则会出现内存泄漏。这也包括您的节点。您可以编写析构函数(例如
~Node(){…}
)这对您来说就是这样。(这是确保类自身清理的正确方法)例如
~Node(){while(head){Node*victor=head;head=head->next;delete victor;}}
另外,如果您添加
tail
指针(例如
Node*head,*tail;
)并且始终让
tail
指向列表中的最后一个节点,您可以在O(1)时间内
追加
,无需迭代。旁注:习惯于实现构造函数的初始化器列表(不要与
std::initializer\u list
混淆):
list():head(nullptr){这比默认的初始化和分配更容易直接初始化,此外,一些成员类型(const,引用,不可分配的)只能用这种方式初始化。此外,你应该更喜欢C++(关键字:代码> nulpPTR <代码>),而不是旧的(过时的)C宏(<代码> null < /代码>)。虽然对学习很好,但请记住,现在已经有了完全相同的方法,您以后应该使用它们,而不是重新发明的轮子。关于学习:下一步是将列表转换为模板,以便能够添加任意数据类型。