【问题标题】:Using the destructor to free linked objects使用析构函数释放链接对象
【发布时间】:2014-06-05 16:45:08
【问题描述】:

我有一个名为“节点”的类。我将一堆节点对象链接在一起形成一个链表。当调用“节点”析构函数时,它只删除第一个节点。如何遍历整个节点链表并删除每个节点对象?

这是类定义:

class Node
{
private:
double coeff;
int exponent;
Node *next;
public:

Node(double c, int e, Node *nodeobjectPtr)
{
    coeff = c;
    exponent = e;
    next = nodeobjectPtr;
}

~Node()
{
    printf("Node Destroyed");
}

通过在指向链接节点列表的第一个节点的指针上调用 delete 来调用析构函数。

【问题讨论】:

  • 如果您只有几个节点,只需执行delete next - 它会递归地破坏节点。如果你有几百或几千个,创建一个LinkedList 对象并在其中迭代地删除它们,否则你会出现堆栈溢出。
  • “如果你只有几个节点” - 你怎么知道?如果有太多,你刚刚炸毁了堆栈。在 C++ 中,无限递归总是一个坏主意。
  • 让链表删除它需要删除的节点,不给节点类这个责任。 delete next 建议只会将 OP 画在角落里。如果稍后,所有需要删除的只是列表中的单个节点怎么办? delete next 将是灾难性的。

标签: c++ class linked-list destructor


【解决方案1】:

如何遍历整个节点链表并删除每个节点对象?

如果你有一个单独的类来管理整个列表,那就是cleaner,这样节点就可以是简单的数据结构。然后你只需要在列表的析构函数中进行一个简单的循环:

while (head) {
    Node * victim = head;
    head = victim->next;    // Careful: read this before deleting
    delete victim;
}

如果您真的想将列表管理委托给节点本身,则需要更加小心:

while (next) {
    Node * victim = next;
    next = victim->next;
    victim->next = nullptr;  // Careful: avoid recursion
    delete victim;
}

在此方案下,从列表中删除节点后删除节点时也需要小心 - 再次确保重置其指针,以免删除列表的其余部分。这是支持单独的“列表”类的另一个原因。

【讨论】:

    【解决方案2】:

    由于您不知道列表中有多少个节点,因此如果您没有明确的界限,递归调用析构函数不是一个好主意,因为每次调用都会使用一些堆栈空间,以及何时可用的堆栈空间筋疲力尽,你会得到未定义的行为,比如崩溃。

    因此,如果您绝对想在节点的析构函数中释放以下节点,则必须先取消链接每个节点,然后再销毁它。

    可以这样:

    Node* unlink( Node*& p )
    {
        Node* result = p;
        p = p->next;
        result->next = nullptr;
        return result;
    }
    
    Node::~Node()
    {
        while( next != nullptr )
        {
            delete unlink( next );
        }
    }
    

    但更好的是,创建一个拥有链表中节点所有权的 List 对象。

    当然,除非这是出于学习目的,或者有充分的理由推出您自己的链表,否则只需使用 std::vector(是的,我的意思是,不是 std::list)。

    【讨论】:

      猜你喜欢
      • 2011-01-06
      • 1970-01-01
      • 2018-11-19
      • 2016-10-25
      • 1970-01-01
      • 2014-11-12
      • 1970-01-01
      • 2012-08-29
      • 2021-11-30
      相关资源
      最近更新 更多