【问题标题】: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伴随着移动,你的其余评论都不会出现在这段代码中。你在说什么?

标签: c++ pointers memory-management


【解决方案1】:

在 C++ 中,当您删除堆上的对象时,实际上并没有清理任何东西,它只是将内存标记为“空闲”。这意味着再次调用 newmalloc 可能会覆盖该内存。

访问已删除的指针是未定义的行为,因为它们不能保证驻留在那里的数据。我不太精通操作系统如何处理内存,但我相信如果这是您从该部分内存中删除的最后一项,您的程序甚至可能不再拥有该页面。如果发生这种情况,那么取消引用该指针将导致大多数桌面操作系统出现分段错误。

如果您想安全地移动头部,您应该在指针处于活动状态时为下一项分配一个临时值,然后您可以从内存中删除底层对象。

【讨论】:

    【解决方案2】:

    删除数据后,指针变为未定义,并且肯定不会到达之前指向的内存,因此删除后无法调用tmp=tmp->next'

    正确的析构函数声明应该是:

    ~LinkedList()
    {
        while (head != nullptr)
        {
            Node * tmp = head->next;
            delete head;
            head = tmp;
        }
    }
    

    顺便说一句:请阅读一些关于如何实现列表的好书。

    BTW.2:如果您确实需要,请使用一些标准容器,例如 vectorlist

    【讨论】:

    • C++ 在取消引用指针之前不会进行内存边界检查或验证。如果它们之前是有效的内存,只要应用程序仍然拥有该内存页,就可以取消引用它。当该位置的数据不再代表有效对象(已被覆盖)时,由于任何内部指针现在是完全不同的数据,导致在原始对象之外的内存上发生读取/写入,您很可能会遇到错误.
    • 指针没有“变得未定义”;并且肯定它指向它之前指向的相同内存。问题是这个内存现在被释放了,所以它可能随时被覆盖,甚至映射出用户的地址空间。 OP 的代码可能大部分时间都可以工作。
    猜你喜欢
    • 1970-01-01
    • 2012-12-17
    • 2011-01-25
    • 1970-01-01
    • 2013-10-14
    • 1970-01-01
    • 2017-07-16
    • 2018-09-04
    • 1970-01-01
    相关资源
    最近更新 更多