【问题标题】:How to delete a pointer stored within a node?如何删除存储在节点中的指针?
【发布时间】:2022-01-14 21:42:30
【问题描述】:

我正在尝试建立一个由包含指向对象的指针的节点组成的二叉树,但是在我的“清除树”函数中,当我尝试释放节点内指针处的内存时遇到了读取访问冲突。为什么我在根指针处释放内存时没有抛出异常,但在节点内的int指针处有?

抛出异常:读取访问冲突。 是 0x2。

class Tree {
private:
    struct Node {
        int* val = nullptr;
        Node* right = nullptr;
        Node* left = nullptr;
    };
    Node* root = nullptr;

public:
    bool Insert(int* num);
    void Empty();
    bool isEmpty() const;
};

void Tree::Empty()
{
    while (!(root == nullptr)) // Just handling the simplest case for now
    {
        if (root->left == nullptr && root->right == nullptr)
        {
            delete root->val;   // Read access violation 
            delete root;
            root = nullptr;
            break;
        }

        [...]
    }
}

bool Tree::Insert(int* num)
{
    Node* insertion = new Node;
    int* temp = new int(*num);
    insertion->val = temp;

    if (root == nullptr)
    {
        root = insertion;
        return true;
    }

    Node* c_node = root;

    while (true)
    {
        if (*temp == *c_node->val)
        {
            delete temp;
            delete insertion;
            return false;
        }

        if (*temp > *c_node->val)
        {
            if (c_node->right != nullptr)
            {
                c_node = c_node->right;
                continue;
            }

            c_node->right = insertion;
            return true;
        }

        if (c_node->left != nullptr)
        {
            c_node = c_node->left;
            continue;
        }

        c_node->left = insertion;
        return true;
    }
}

int main()
{
    int a = 2;

    Tree my_tree;

    my_tree.Insert(&a);
    my_tree.Empty();
}

如有任何反馈,我将不胜感激!

【问题讨论】:

  • 为了让我们告诉您是否可以删除root->val,您必须显示设置root->val 的代码。另外,您确定root->val 不为空吗?最好为此添加assert。您还应该显示isEmpty 的定义。真的最好提供minimal reproducible example
  • 有点语义,但不要删除指针。但是你用操作符删除释放它指向的内存。如果 root 是指向节点的指针,您是否分配了它?或者它只是 Tree 的成员(注意现代 C++ 中的 new/delete 应该谨慎使用,但我认为这是作业的一部分)
  • 既然可以只存储一个 int,为什么还要在 Node 中存储一个指向 int 的指针?
  • @poisson -- 使int 成为指针太过分了,对于“学习指针”的任务来说完全没有必要。您要存储的数据是int,而不是指针。数据结构(在本例中为二叉树)是通过使用指针来维护的,但这与存储在节点上的数据完全无关。

标签: c++ pointers binary-tree


【解决方案1】:

我建议先让Node 对自己的内容负责:

struct Node {
    Node(int *val) : val(new int(*val)) { }
    int* val = nullptr;
    Node* right = nullptr;
    Node* left = nullptr;
    ~Node() { delete val; }
};

完成此操作后,我们可以稍微简化Empty(和Insert)的代码,让它处理它所存储的值,所以到目前为止您实现的Empty 的片段最终会有所作为像这样:

void Tree::Empty()
{
    while (!(root == nullptr)) // Just handling the simplest case for now
    {
        if (root->left == nullptr && root->right == nullptr)
        {
            delete root;
            root = nullptr;
            break;
        }
    }
}

至于使这个实现适用于具有多个节点的树,我可能会递归地进行:

void Tree::Empty(Node *node)
{
    if (node == nullptr)
        return;

    Empty(node->left);
    Empty(node->right);

    delete node;
}

我可能还会为Tree 定义一个dtor,因此用户不需要显式调用Empty(实际上,我可能会将Empty 设为私有,所以外界不能完全调用它,但这是一个单独的问题)。

【讨论】:

  • 让 Node 负责自己的分配和解除分配,构造函数/析构函数解决了所有访问冲突异常。非常感谢您的时间和帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-15
  • 1970-01-01
  • 1970-01-01
  • 2019-12-02
  • 1970-01-01
相关资源
最近更新 更多