我需要删除单链表中动态分配的对象吗?

Posted

技术标签:

【中文标题】我需要删除单链表中动态分配的对象吗?【英文标题】:Do I need to delete a dynamically allocated object in Singly Linked List? 【发布时间】:2021-06-07 04:28:22 【问题描述】:

我目前正在学习链接列表,并且已经使用 Append 和 Prepend 方法实现了一个单链表,其中我使用“new”运算符在堆上分配了 Node 类型的对象。我是否需要使用“删除”在堆上释放对象,如果需要,我该怎么做? 这是我的代码:-

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;
    

【问题讨论】:

Any 如果不再需要动态分配的数据,则需要为deleted,否则会出现内存泄漏。这也包括您的节点。 你可以编写一个析构函数(例如~Node() ... )来为你做这件事。 (这将是确保班级自行清理的正确方法)例如~Node() while (head) Node *victim = head; head = head-&gt;next; delete victim; 另外,如果你添加一个tail指针(例如Node *head, *tail;)并且总是让tail指向你列表中的最后一个节点,你可以在O(1)时间内append无需迭代。 旁注:习惯于实现构造函数的初始化列表(不要与std::initializer_list混淆):List() : head(nullptr) 。这比默认初始化+赋值更喜欢直接初始化,另外一些成员类型(常量、引用、不可赋值的)only 可以这样初始化。此外,您应该更喜欢 C++ keywords (nullptr) 而不是旧的(过时的?)C macros (NULL)。 虽然适合学习,但请记住std::forward_list 已经在做同样的事情,你应该稍后使用它而不是重新发明的***。关于学习:下一步是将您的列表转换为模板,以便能够添加任意数据类型。 【参考方案1】:

对于初学者来说这个构造函数

    Node(const int& data)
    
        this->data = data;
    

不初始化数据成员next。因此成员函数AppendPrepend 有一个错误

void List::Append(const int&val)

    Node* n = new Node(val); //dynamically allocated 
    if (head == NULL)
    
        head = n;
        return;
    
    //...

void List::Prepend(const int&val)

    Node* node = new Node(val);//dynamically allocated 
    if (head == NULL)
    
        head = node;
        return;
    
    //...

头节点的数据成员next有一个不确定的值。

你可以简单地声明类Node

struct Node

    int data;
    Node* next;
;

Node* head = nullptr;

在这种情况下,例如函数 Prepend 看起来像

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(); 
    //...

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

【讨论】:

以上是关于我需要删除单链表中动态分配的对象吗?的主要内容,如果未能解决你的问题,请参考以下文章

我可以删除以前动态分配但使用不同指针的内存吗?

单链表

当它们的容器被破坏时,如何删除这些动态分配的对象?

如果 C++ 程序发生错误,如何删除动态分配的对象?

动态内存分配

在 C++ 循环中正确删除动态分配的对象的位置