下一步); cout,c++,pointers,c++11,C++,Pointers,C++11" /> 下一步); cout,c++,pointers,c++11,C++,Pointers,C++11" />

如何";完全;是否删除链接列表中的所有节点? 我对C++中指针和删除指针如何工作感到好奇,于是我做了一个实验。我制作了一个非常简单的单链表和以下递归函数,用于删除列表中的所有节点: void deleteList(Node *node) { if (!node) return; deleteList(node->next); cout << "deleting node " << node->data << endl; delete node; node = nullptr; } 无效删除列表(节点*节点){ 如果(!节点) 回来 删除列表(节点->下一步); cout

如何";完全;是否删除链接列表中的所有节点? 我对C++中指针和删除指针如何工作感到好奇,于是我做了一个实验。我制作了一个非常简单的单链表和以下递归函数,用于删除列表中的所有节点: void deleteList(Node *node) { if (!node) return; deleteList(node->next); cout << "deleting node " << node->data << endl; delete node; node = nullptr; } 无效删除列表(节点*节点){ 如果(!节点) 回来 删除列表(节点->下一步); cout,c++,pointers,c++11,C++,Pointers,C++11,您释放了内存,但是对nullptr的赋值只影响传递给函数的指针的副本,而不影响调用者中的原始指针 如果将函数声明为通过引用接收指针: void deleteList(Node *&node) { 那么node=nullptr;的赋值也会影响调用者 请注意,由于您标记了这个C++11,因此通常更简单的方法是将链表定义为正向的一系列std::unique_ptrs(如果是双向的,则反向的原始指针以避免引用循环)因此,您可以避免需要特殊的删除器功能,只需将头指针设置为 nulLPTR < /

您释放了内存,但是对
nullptr
的赋值只影响传递给函数的指针的副本,而不影响调用者中的原始指针

如果将函数声明为通过引用接收指针:

void deleteList(Node *&node) {
那么
node=nullptr;
的赋值也会影响调用者

请注意,由于您标记了这个C++11,因此通常更简单的方法是将链表定义为正向的一系列
std::unique_ptr
s(如果是双向的,则反向的原始指针以避免引用循环)因此,您可以避免需要特殊的删除器功能,只需将头指针设置为<代码> nulLPTR < /C> >并让C++完成删除的工作。
Edit:让
std::unique_ptr
完成工作有一个缺陷;正如评论中指出的,这意味着列表大小实际上受到堆栈的限制,太大的列表在删除它们时会导致堆栈溢出。因此,请逐个明确清除(最简单的方法是正确地实现弹出,并让清除操作简单地弹出,直到
head
通过
popleft
方法转换为
nullptr
)这样会更安全。我将原始建议留待后人使用,因此此解释很有意义。

您释放了内存,但分配给
nullptr
只会影响传递给函数的指针的副本,而不会影响调用者中的原始指针

如果将函数声明为通过引用接收指针:

void deleteList(Node *&node) {
那么
node=nullptr;
的赋值也会影响调用者

请注意,由于您标记了这个C++11,因此通常更简单的方法是将链表定义为正向的一系列
std::unique_ptr
s(如果是双向的,则反向的原始指针以避免引用循环)因此,您可以避免需要特殊的删除器功能,只需将头指针设置为<代码> nulLPTR < /C> >并让C++完成删除的工作。
Edit:让
std::unique_ptr
完成工作有一个缺陷;正如评论中指出的,这意味着列表大小实际上受到堆栈的限制,太大的列表在删除它们时会导致堆栈溢出。因此,请逐个明确清除(最简单的方法是正确地实现弹出,并让清除操作一直弹出,直到
popleft
方法将
head
转换为
nullptr
)会更安全。我将最初的建议留给了后代,所以这个解释是有意义的。

List();
不是你所想的。是的,在我的实验中,我实际上有两个构造函数。我上面的例子中的一个调用另一个构造函数,它初始化值,如大小为0和一个新的空头节点。该语句根本不调用构造函数。它是一个返回类型为
list
的函数的声明或者对象初始化,
()
需要删除。哦,你完全正确。不知道我当时在想什么;不是你所想的。是的,在我的实验中,我实际上有两个构造函数。我上面的例子中的一个调用另一个构造函数,它初始化值,如大小为0和一个新的空头节点。该语句根本不调用构造函数。它是一个返回类型为
list
的函数的声明或者对象初始化,
()
需要删除。哦,你完全正确。不知道我当时在想什么。完美,谢谢你的澄清。我以为指针总是通过引用传递的。这是我第一次听说独特指针(如果它们被称为?).我需要更多地了解these@MannyKim:是的,.指针很有趣,因为指针本身是通过值传递的;两个指针最初都引用相同的内存,但更改被调用方中的指针不会影响调用方,只会更改指向的数据(其中包括释放该位置的内存的效果;不要取消引用您知道已被另一个函数释放的指针)。请明确,“释放的指针”指的是“删除节点”,“取消引用指针”指的是“node=nullptr”,对吗?谢谢你提供的额外细节,这真的让它更容易理解pointers@MannyKim:“释放”和“删除”是等价的;在C中,使用<代码>免费> /Cuff>函数,在C++中使用<代码>删除< /C>关键字(虽然在理想情况下,您可以使用智能指针,如
unique\u ptr
shared\u ptr
,以避免需要显式使用
delete
)。取消引用指针意味着实际使用它来查找数据,使用
*
->
。删除指针实际上也会有效地取消引用(删除两次是严重错误)赋值<代码> null ptr>代码>既不删除也不释放哑指针,但对于唯一指针,它等同于同时删除和清除指针。让C++进行递归数据结构的级联删除会导致堆栈溢出。谢谢,请澄清。我想指针Were总是通过引用传递。这是我第一次听说独特指针(如果它们被称为什么?),我需要了解更多these@MannyKim:是的,。指针很有趣