我很好奇指针和删除指针如何在C ++中工作,所以我设置了一个实验。我创建了一个非常简单的单链表和以下递归函数,删除列表中的所有节点:
void deleteList(Node *node) {
if (!node)
return;
deleteList(node->next);
cout << "deleting node " << node->data << endl;
delete node;
node = nullptr;
}
我认为这会成功删除列表中的所有节点。但是,在main中调用此函数后,我检查头节点是否仍然存在:
List list;
// appending a bunch of numbers to the list...
list.deleteList(list.head);
if (list.head)
cout << true;
这将打印1到控制台,这意味着头部确实仍然存在。我希望head和它之后的所有其他节点都为null,因此if条件失败,因为将指针设置为null是我在递归函数中做的最后一件事。那么为什么程序会报告头部仍然存在?
编辑:更改列表列表();列表清单;
答案 0 :(得分:4)
释放了内存,但是nullptr
的赋值只影响了传递给函数的指针的副本,而不影响调用者中的原始指针。
如果您将该函数声明为通过引用接收指针:
void deleteList(Node *&node) {
然后node = nullptr;
的分配也会影响来电者。
请注意,由于您标记了此C ++ 11,因此将链接列表定义为正向的一系列 std::unique_ptr<Node>
通常要简单得多(反向的原始指针,如果它是双向的,以避免引用循环),因此您可以避免需要特殊的删除函数,只需将头指针设置为nullptr
,让C ++完成级联删除的工作。
编辑:让std::unique_ptr
做工作有一个缺陷;正如注释中所指出的,这意味着列表大小实际上受到堆栈的限制,而过大的列表会在删除堆栈时导致堆栈溢出。因此,逐个明确地清除(最简单的方法是正确实现弹出,并且只需弹出清除,直到head
通过nullptr
方法转换为popleft
)才会更安全。我为后人留下了原来的建议,所以这个解释是有道理的。