C++ 如何销毁包含自引用指针的对象?

C++ 如何销毁包含自引用指针的对象?,c++,pointers,memory-management,destructor,delete-operator,C++,Pointers,Memory Management,Destructor,Delete Operator,我有一个树节点结构,其简单定义如下: typedef struct TreeNode { int data; TreeNode *left; TreeNode *right; TreeNode *parent; TreeNode(int); ~TreeNode(); } TreeNode; 为了在销毁时释放左、右和父对象指向的内存(假设不为空),我制作了一个析构函数,如下所示: TreeNode::~TreeNode() { delet

我有一个树节点结构,其简单定义如下:

typedef struct TreeNode {
    int data;
    TreeNode *left;
    TreeNode *right;
    TreeNode *parent;

    TreeNode(int);
    ~TreeNode();
} TreeNode;
为了在销毁时释放
父对象
指向的内存(假设不为空),我制作了一个析构函数,如下所示:

TreeNode::~TreeNode() {
    delete left;
    delete right;
    delete parent;
}
但是,这样做会导致控件无限递归地删除
TreeNode
对象,因为析构函数中的那些
delete
语句调用相同结构的析构函数


问题:

  • 释放自引用指针的正确方法是什么,特别是在析构函数内部

如果不调用父析构函数,它应该可以工作。但是,如上所述,该节点下的整个树将被删除

如果不调用父析构函数,它应该可以工作。但是,如上所述,该节点下的整个树将被删除

正确的方法是不要使用自己的原始指针,而是为子级使用
std::unique\u ptr

如果还去掉了多余的
typedef
,则结构如下所示:

struct TreeNode {
    int data;
    std::unique_ptr<TreeNode> left;
    std::unique_ptr<TreeNode> right;
    TreeNode *parent{nullptr};

    TreeNode() = default;
};
结构树节点{ int数据; std::唯一左上角; std::唯一的ptr权限; 树节点*父节点{nullptr}; TreeNode()=默认值; };
现在,您无需执行任何操作,编译器将为您生成正确的解构器。

正确的方法是不要使用拥有的原始指针,而是为子级使用
std::unique\u ptr

如果还去掉了多余的
typedef
,则结构如下所示:

struct TreeNode {
    int data;
    std::unique_ptr<TreeNode> left;
    std::unique_ptr<TreeNode> right;
    TreeNode *parent{nullptr};

    TreeNode() = default;
};
结构树节点{ int数据; std::唯一左上角; std::唯一的ptr权限; 树节点*父节点{nullptr}; TreeNode()=默认值; };
现在您不需要做任何事情,编译器将为您生成正确的解构器。

您最好阅读
std::unique\u ptr
std::shared\u ptr
std::weak\u ptr
。您不应该有一个包含
TreeNode
类吗,而
类在必要时创建和销毁节点?您当前的设计通过删除单个节点来分解整个树。“如果你想删除一个节点?”杰斯珀,我真的只是从C++开始,所以直到我知道基本知识,然后我才会转到更高级的东西:D@Christian使用
new
delete
处理拥有原始指针和手动管理内存是高级功能。@你误解了。我试着给你们指出一个简单解决方案的方向。通过使用(老式的)手动内存管理,您已经走上了艰难的道路。您最好阅读
std::unique_ptr
std::shared_ptr
std::weak_ptr
。您不应该有一个包含
TreeNode
类吗,而
类在必要时创建和销毁节点?您当前的设计通过删除单个节点来分解整个树。“如果你想删除一个节点?”杰斯珀,我真的只是从C++开始,所以直到我知道基本知识,然后我才会转到更高级的东西:D@Christian使用
new
delete
处理拥有原始指针和手动管理内存是高级功能。@你误解了。我试着给你们指出一个简单解决方案的方向。通过使用(老式)手动内存管理,您已经开始走上了艰难的道路。对下行表决有何评论?是否调用父析构函数,只要我调用以删除父方法中的某个树节点;它会导致控件无限“递归”。你错了,因为如果(left){delete left;left=0;},如果(left){delete left;left=0;},它应该停止。如果(left){delete left=0;}有任何关于向下投票的注释吗?只要我调用父析构函数删除父方法中的某个树节点,就不会调用父析构函数;它会导致控件无限“递归”。这是错误的,因为如果(左){delete left;left=0;}