C++ 是否需要删除单链表中动态分配的对象?
我目前正在学习链表,并实现了一个带有Append和Prepend方法的单链表,其中我使用“new”操作符在heap上分配了Node类型的对象。我是否需要使用“delete”取消分配堆上的对象,如果需要,我该怎么做? 这是我的密码:-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
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 < /代码>)。虽然对学习很好,但请记住,现在已经有了完全相同的方法,您以后应该使用它们,而不是重新发明的轮子。关于学习:下一步是将列表转换为模板,以便能够添加任意数据类型。