链接的链接析构函数引发分段错误

Linked linked destructor raises segmentation fault

我正在尝试使用析构函数删除链表。

但是这段代码给出了一个分段错误:

~Node()
{
    Node *current = this ;
    Node *previous = NULL;
    while(current != NULL)
    {
        previous = current;
        current = current->next;
        delete previous;
        previous = NULL;
    }
}

我做错了什么?

您不能删除当前节点本身,否则代码会调用未定义的行为。

你可以这样写

~Node()
{
    delete next;
}

并且如果列表被定义为指向头节点的指针那么你需要写

delete head;

这里是演示程序

#include <iostream>

class Node
{
private:
    int data;
    Node *next;

public:

    explicit Node( int data, Node *next = nullptr ) : data( data ), next( next )
    {
    }

    ~Node()
    {
        std::cout << "Deleting " << data << "...\n";
        delete next;
    }
};

void push_front( Node *&head, int data )
{
    head = new Node( data, head );
}

int main()
{
    Node *head = nullptr;
    const int N = 10;

    for (int i = 0; i < N; i++)
    {
        push_front( head, N - i );
    }

    delete head;
}

程序输出为

Deleting 1...
Deleting 2...
Deleting 3...
Deleting 4...
Deleting 5...
Deleting 6...
Deleting 7...
Deleting 8...
Deleting 9...
Deleting 10...

您应该从 delete 运算符中排除当前节点,因为代码已经是对 delete 的响应。再做一遍就像运行转圈一样。

所以将您的代码修改为:

~Node()
{
    Node *current = this->next; // exclude current node
    Node *previous;

    while (current != NULL)
    {
        previous = current;
        current = current->next;
        previous->next = NULL; // avoid the delete below to propagate through list.
        delete previous;
    }
}

没有必要将 previous 设置为 NULL,因为它会 运行 超出范围。但是需要将 previous 与其后继者分离,以避免析构函数再次跟随该链。

此代码假定 this 是列表的 first 节点,这将是执行 delete 的自然结果。如果出于某种原因您要在列表中间某处的节点上执行 delete ,目的是丢弃整个列表,那么您还需要对当前节点之前的节点重复上述循环.