【问题标题】:How to delete dynamically allocated struct consisting dynamically allocated array member in C++?如何在 C++ 中删除由动态分配的数组成员组成的动态分配的结构?
【发布时间】:2017-06-11 07:07:16
【问题描述】:

我正在做作业,要求我在不使用向量的情况下实现 Trie 树。我有一个struc 定义如下:

typedef struct{
    char _name;
    int32_t * _children;
    int32_t _children_size;
    int32_t _children_capacity;
    int32_t * _location;
    int32_t _location_size;
    int32_t _location_capacity;
} TrieTreeNode;

为了减少内存使用,我将TrieTreeNode的所有指针存储到一个全局变量TrieTreeNode ** nodes_array中。那么每个TrieTreeNode_children 成员只是一个数组,其元素是int32_tnodes_array 的索引。

例如,假设我们有TrieTreeNode * parent。要访问它的第一个孩子,我们使用nodes_array[parent -> _children[0]]

我的问题是如何删除整个特里树?我尝试了以下方法(tailnodes_array 拥有的指针数量):

void delete_node(TrieTreeNode *node){
    delete [] node -> _children;
    delete [] node -> _location;
}

void delete_tree(){
    for (int i = 0; i < tail; i++){
        delete_node(nodes_array[i]);
    }
    delete [] nodes_array;
    nodes_array = NULL;
}

但是,当我同时使用-ps -l 命令和 GDB 来监控我的程序在删除树之前和之后的内存使用情况时,内存只减少了一点点。 RRS 从 13744 变为 13156,而在我构建树之前它只有 1072。

任何建议将不胜感激!

【问题讨论】:

  • 为什么你不使用析构函数而不是delete_node/delete_tree?而typedef struct 在 C++ 中是不必要的。
  • "为了减少内存使用,我将 TrieTreeNode 的所有指针存储到一个全局变量 TrieTreeNode ** nodes_array" 你为什么认为使用全局变量会减少内存使用?为什么你认为减少内存使用很重要?此外,C++ 不需要那个 typedef。
  • @NeilButterworth 我认为也没有必要,但是这项作业的一个要求是减少内存。我认为使用 int32_t 而不是 64 位指针可能更有效。这可能是错误的,所以我也期待您的建议。
  • 谁投了反对票,请留下您的评论,以便我改进我未来的问题。谢谢。
  • 即使不允许使用std::vector 和智能指针,也请开始编写自己的类来处理它,然后在此基础上进行构建。

标签: c++ pointers memory memory-management struct


【解决方案1】:

您没有删除节点,只是删除每个节点内的指针。

考虑一下:

void delete_tree(){
    for (int i = 0; i < tail; i++){
        delete_node(nodes_array[i]);
        delete node_array[i];  // Delete the node itself.
    }
    delete [] nodes_array;
    nodes_array = NULL;
}

在调用delete_node 释放每个节点中的两个指针后,您应该删除节点本身delete node_array[i] 以释放每个节点的剩余内存。

不过,就我个人而言,我喜欢为结构定义构造函数和析构函数,这样我就不必记住在创建它们的任何地方都进行初始化,或者在我可能处置的任何地方进行额外的删除。

【讨论】:

  • 对不起,我尝试了你的代码,但它不起作用(我没有对你投反对票)。
  • @JayWong 它会崩溃,还是无法删除内存?根据我对您的代码的了解,我相当确定这些节点至少代表了您的部分泄漏。
  • 不,它不会崩溃。 RRS 仍然没有显着变化。我正在研究 struct 的析构函数。
  • @JayWong 请考虑泄漏发生在您的 trie 树的其他操作中的可能性。
  • @JayWong 我同意 Mikel F 的观点。结构上的析构函数将简化清理工作,但也给它一个构造函数来初始化 _children_location 指向 nullptr 的指针以防止如果没有设置_children_location 就破坏了结构体,这会很糟糕。另外,知道Rules about using an underscore in a C++ identifier 以防止令人讨厌的意外。当然,如果你一开始没有成功,那就再试一次。
猜你喜欢
  • 1970-01-01
  • 2020-05-26
  • 2017-12-10
  • 1970-01-01
  • 2020-03-06
  • 1970-01-01
  • 2014-08-22
  • 2018-05-01
  • 2019-07-19
相关资源
最近更新 更多