首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >这个单链接的列表析构函数是如何导致无限循环的?

这个单链接的列表析构函数是如何导致无限循环的?
EN

Stack Overflow用户
提问于 2018-12-14 09:09:42
回答 2查看 263关注 0票数 1

我使用一个struct编写了一个单链接列表实现。它不是管理列表上的操作的外部类的一部分。相反,所有的操作都由节点直接处理。

我理解,如果struct定义是类的一部分,比方说ListManager,那么调用ListManager实例上的析构函数只需要迭代由类管理的链接列表并删除每个节点。

但是,由于这个链接列表不是外部类的一部分,并且管理所有操作本身,所以我对如何编写析构函数感到有点困惑。

版本1运行良好,它是一个递归调用,遍历列表,释放与每个节点相关的内存。

版本2导致无限循环。我不明白为什么,因为这是我为管理Node链接列表的容器类实现析构函数的一种方法。

第3版运行良好,但过于冗长。

我运行了这三个版本,使用val差生和python家教检查泄漏和其他问题。

任何帮助解释为什么版本2不工作,为什么它是不正确的,以这种方式实现析构函数是值得赞赏的!

结构链表

代码语言:javascript
复制
#include <iostream> 
#include <string> 
using namespace std; 

struct Node
{   
    int id; 
    Node* next; 
    Node(int newId = 0, Node* newNext = NULL)
    : id(newId), next(newNext) { } 
};

析构函数版本1

代码语言:javascript
复制
~Node()
{
    if (next != NULL)
        delete next; 
}

析构函数版本2

代码语言:javascript
复制
~Node()
{
    Node* lead = this; 
    Node* follow = this;

    while (follow != NULL)
    {
        lead = lead->next; 
        delete follow; 
        follow = lead; 
    }
}

析构函数版本3

代码语言:javascript
复制
~Node()
{
    Node* lead = this; 
    Node* follow = this;

    if (follow != NULL)
    {
        lead = lead->next; 
        delete follow; 
        follow = lead; 
    }
}

代码语言:javascript
复制
int main()
{
    Node* head = NULL; 
    head = new Node(23, head); 
    head = new Node(54, head); 
    head = new Node(81, head);
    head = new Node(92, head); 
    delete head;     
    return 0; 
}
EN

回答 2

Stack Overflow用户

发布于 2018-12-14 09:15:33

在第2版中,您已经编写了一个循环,通过循环遍历列表并删除每个元素,从而在一个析构函数调用中清除整个列表。但是,所发生的并不是只有一个析构函数调用。每次删除元素时,都会再次调用析构函数。

因此,最后,对于第一次调用,delete follow转换为delete this (因为follow = this;)。这将导致再次调用第一个节点的析构函数,从而导致无穷无尽的循环。

下面的节点将被多次销毁,导致未定义的行为,但由于无限循环,它甚至没有到达那里。

票数 3
EN

Stack Overflow用户

发布于 2018-12-14 09:38:12

您只需要每个Node删除(最多)另一个Node,最终删除所有节点。重新分配本地指针不会影响列表的结构。

2和3都是delete this,在最好的时候是可疑的,再加上一些无关的仪式,在破坏者中。它们都是未定义的行为,删除同一对象(至少)两次。

你的第一次尝试已经接近了。

不要将自己与指针值的复制混淆在一起,只需使用拥有的指针类型,比如std::unique_ptr

代码语言:javascript
复制
struct Node
{   
    int id; 
    std::unique_ptr<Node> next; 
    Node(int id = 0, std::unique_ptr<Node> next = {})
    : id(id), next(std::move(next)) { } 
    // correct destructor is implicit
};
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53776528

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档