【问题标题】:Destructor always hitting Null析构函数总是命中 Null
【发布时间】:2018-08-14 17:18:04
【问题描述】:

我今天正在玩链表。 尽管我似乎总是遇到同样的问题,但我的一切工作都很好,无论如何,析构函数似乎总是在以任何形式访问析构函数时遇到 NULL 对象,抛出“访问权限冲突错误”

“this->next”是“0xDDDDDDDD”。

struct Liste {
Liste *next;
int content;
Liste() {
    content = 0;
    next = nullptr;
};
~Liste() {
    if (next == nullptr) {
        return;
    }else if (next->next == nullptr){
        delete next;
        return;
    }else {
        next->~Liste();
    }
};
};

我非常不确定和好奇这个错误的来源。 无论我尝试在其上使用删除的方式,它总是会发生。 到目前为止我找到的解决方案是: - 只需在第一个元素上调用 delete 并调用其他元素的析构函数 - 尝试检查下一行是否为空,但它似乎根本没有过滤掉它 -尝试迭代地通过它,但这也确实遇到了零 - 尝试在一个确实可以正常工作的类中实现它,直到我不得不实现一个遇到完全相同错误的删除

我很高兴收到一些有关如何修复/避免此问题的提示,因为根本不删除它不是一个好主意,而且我完全不确定代码中到底出了什么问题。

【问题讨论】:

标签: c++ recursion linked-list


【解决方案1】:

你的析构函数只需要:

~Liste() {
    delete next;
}

如果next 不是null,那么delete next; 会调用下一个元素的析构函数,而后者又会调用下一个元素的析构函数,以此类推。如果nextnull 那么delete next; 不会做任何事情,这很好。

【讨论】:

  • 这是溢出堆栈的秘诀。你递归到n的深度
  • 在空指针上调用 delete 已经不是以前那样了。 stackoverflow.com/questions/25329576/….
  • @alterigel 也许,但也要考虑在没有优化的情况下在调试中运行是很常见的情况。根据经验,只有当您可以将堆栈增长保持为 O(log n) 时才进行递归
  • 我希望 C++ 有尾递归优化。 :-(
  • @Eljay 我正在等待心灵感应编译器。一种生成的代码可以按照您的意愿执行,而不是按照您的指示执行。
【解决方案2】:

previous answer相比没有堆栈溢出:

~Liste() {
     Liste* temp = nullptr;
     while (next) {
         temp       = next->next;
         next->next = nullptr;
         delete next;
         next       = temp;
     }
 }

关于给定的代码:

~Liste() {
    if (next == nullptr) {
        return;
    } else if (next->next == nullptr){
        delete next;
        return;
    } else {
        next->~Liste(); // *next is destructed, but next is not deallocated!
    }
};

虽然,给定的代码(包括析构函数)可能不是 Slava 已经提到的内存访问错误的原因。

【讨论】:

  • 我认为正确的解决方案是为节点和列表本身设置单独的类,并在列表的析构函数中实现此逻辑。这里列表链接到另一个列表,实际上是一个节点。
  • @Slava 确实;我曾经写过一个doubly linked list,它使用一个单独的类来表示链接。
  • 我认为几乎每个人都曾在某个时间点编写过双向链表程序。天啊,过一段时间再标记这些东西一定很无聊。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-16
  • 2013-08-01
  • 2019-04-20
  • 2011-03-21
  • 1970-01-01
  • 2013-08-15
  • 2016-02-20
相关资源
最近更新 更多