在链表中删除该节点时,Node* 接下来会发生啥?
Posted
技术标签:
【中文标题】在链表中删除该节点时,Node* 接下来会发生啥?【英文标题】:What happens to Node* next when deleting that Node in a linked list?在链表中删除该节点时,Node* 接下来会发生什么? 【发布时间】:2019-04-09 10:21:52 【问题描述】:在使用
的链表中struct Node
T value;
Node* next;
对于每个使用的 new 运算符(new Node())
,必须有一个 delete 运算符。
此类列表的析构函数示例
~LinkedList()
Node* tmp = head;
while(tmp! = nullptr)
delete tmp;
tmp = tmp->next;
我的问题是,究竟是什么被“删除”,让我可以使用 next 指针 即使在使用 delete 之后?它只删除值吗?它在记忆中的实际表现如何?
【问题讨论】:
delete 伴随着一个动作。链表中前一个元素的下一个元素现在指向被删除元素之后的元素。 您的代码有错误。如果你打电话给delete tmp
然后在 tmp->next 你会得到访问冲突或类似的东西
tmp->next
after delete tmp
可能有时会起作用,但这是严格未定义的行为。
@MichaelChourdakis 不在此代码中。
@MichaelChourdakis delete
是不伴随着移动,你的其余评论都不会出现在这段代码中。你在说什么?
【参考方案1】:
在 C++ 中,当您删除堆上的对象时,实际上并没有清理任何东西,它只是将内存标记为“空闲”。这意味着再次调用 new
或 malloc
可能会覆盖该内存。
访问已删除的指针是未定义的行为,因为它们不能保证驻留在那里的数据。我不太精通操作系统如何处理内存,但我相信如果这是您从该部分内存中删除的最后一项,您的程序甚至可能不再拥有该页面。如果发生这种情况,那么取消引用该指针将导致大多数桌面操作系统出现分段错误。
如果您想安全地移动头部,您应该在指针处于活动状态时为下一项分配一个临时值,然后您可以从内存中删除底层对象。
【讨论】:
【参考方案2】:删除数据后,指针变为未定义,并且肯定不会到达之前指向的内存,因此删除后无法调用tmp=tmp->next'
。
正确的析构函数声明应该是:
~LinkedList()
while (head != nullptr)
Node * tmp = head->next;
delete head;
head = tmp;
顺便说一句:请阅读一些关于如何实现列表的好书。
BTW.2:如果您确实需要,请使用一些标准容器,例如 vector
或 list
。
【讨论】:
C++ 在取消引用指针之前不会进行内存边界检查或验证。如果它们之前是有效的内存,只要应用程序仍然拥有该内存页,就可以取消引用它。当该位置的数据不再代表有效对象(已被覆盖)时,由于任何内部指针现在是完全不同的数据,导致在原始对象之外的内存上发生读取/写入,您很可能会遇到错误. 指针没有“变得未定义”;并且肯定它指向它之前指向的相同内存。问题是这个内存现在被释放了,所以它可能随时被覆盖,甚至映射出用户的地址空间。 OP 的代码可能大部分时间都可以工作。以上是关于在链表中删除该节点时,Node* 接下来会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章