【问题标题】:Destructor causing runtime error析构函数导致运行时错误
【发布时间】:2015-09-22 10:41:47
【问题描述】:

出于练习目的,我正在使用 Trees。目前精确的二叉搜索树。我有一个通用的Tree 类,用于解决 BST 问题。 因此,我遇到了将给定树(BST)转换为双向链表的问题。

我能够成功地将树转换为 DLL。但是,问题是当我打电话给destructor 时。 因为,我正在为树的节点分配内存,所以我也希望释放内存。 这是Tree 类的析构函数 ::

~Tree() {
        delete root;
        root = NULL;
    }

这是Node类的析构函数::

~Node() {
        delete left;
        delete right;
        left = NULL;
        right = NULL;
    }

所以,程序最后崩溃了! 据我了解,由于我编写的析构函数会递归删除树的所有节点,并且当 Tree 转换为 DLL 时,左右指针确实相互指向,因此,在调用析构函数期间,析构函数尝试删除已被删除且该指针尚未设置为 NULL 的节点。 我该如何克服呢?由于不允许析构函数重载。

有什么办法可以防止这个运行时错误? 这是代码 :: http://ideone.com/SDkXY9 (ideone不打印输出,不知道为什么!)

【问题讨论】:

  • 哦,将成员变量设置为NULL(顺便说一下,使用0nullptr)只设置that 成员变量,而不是任何其他指针。在析构函数中重置成员变量实际上是没有意义的,因为一旦调用析构函数,对象(及其成员变量)就不再存在了。
  • @user007 这个名字只是一个提示,你可以随便叫它;)
  • 你需要检查你的convertBSTtoDLLUtil函数。当您将 root 设为另一个节点的子节点时,前一个父节点仍将 root 作为子节点,并且您会得到多个父节点具有相同的子节点,从而导致您的问题。
  • @user007 看看你的设计。如果我想删除一个节点,不理会树的其余部分怎么办?这不合理吗?当然不是。如果你不能从树上砍下树枝,那树有什么用?但是,您的设计使这项简单的任务变得不可能。当 Node 被删除时,析构函数会销毁与其连接的所有节点。这听起来像是一个好的设计吗?让Tree 弄清楚在销毁自身时要删除哪些节点。所需要的只是一个简单的递归循环来删除节点。
  • @user007 这真的是一个知道一个节点应该有多少“智能”的问题。该节点应通过Tree 创建、销毁并链接到其他节点。因此,做家务应该是树的责任。通过在 Node 中放置一个析构函数来解除与邻居的链接,你做了一件不可思议的事情——移除一个分支,整棵树就会倒塌。

标签: c++ c++11 tree runtime-error


【解决方案1】:

这里的问题是您试图删除启动链式销毁的邻居。您必须添加一个标志,您可以在析构函数中签入该标志,以便删除邻居。

~Node() {
    _isDestructing = true;
    if (!left->_isDestructing) delete left;
    if (!right->_isDestructing) delete right;
    left = NULL;
    right = NULL;
}

【讨论】:

    猜你喜欢
    • 2016-08-05
    • 2013-04-30
    • 2012-03-09
    • 2014-02-17
    • 2020-09-28
    • 2019-05-31
    • 1970-01-01
    • 2013-08-10
    • 1970-01-01
    相关资源
    最近更新 更多