树结构的C++析构函数

C++ destructor for tree structure

本文关键字:析构函数 C++ 结构      更新时间:2023-10-16

我有这样的树结构:

public:
    node(string& const n);
    virtual ~node();
    string get_name() const;
    void set_name(string& new_name);
    int get_nr_children() const;
    node get_child(int i) const;
    void add_child(node child);
private:
    string& name;
    vector<node> children;
};

我的main.cpp看起来是这样的:

int main() {
    string s = "root";
    node r(s);
    string s2 = "left child";
    node ls(s2);
    string s3 = "right child";
    node rs(s3);
    r.add_child(ls);
    r.add_child(rs);
    r.~node();
}

(我知道~node()main函数结束时在所有对象上运行,但我想确保它首先在根r上执行)

到目前为止,除析构函数外,所有方法都运行良好。这是我的第一个析构函数,我想出了下面的递归尝试,但不知道为什么它不起作用。

node::~node() {
    cout << "Enter ~node of " << this->get_name() << endl;
    while (this->get_nr_children() != 0) {
        this->get_child(0).~node();
        this->children.pop_back();
    }
    delete this;
    cout << "Leave ~node of " << this->get_name() << endl;
}

结果是"Enter ~ node of left child"的无休止输出

"(我知道~node()在主函数结束时会在所有对象上运行,但我想确保它首先在根r上执行)"

这句话足以说明这个问题的一切都是基于误解。

试图纠正甚至没有意义:完全重写是必要的。

相反,请阅读更多关于去分配器、它们的调用以及它们的用途的信息。

显式调用它不会抑制对它的隐式调用。双重破坏是未定义的行为。

此外,delete this是一个非常棘手的问题,要求你必须非常确定它的含义。

并且在删除类方法(this->...)或数据之后访问它们。。。只是在寻找麻烦。

如果编译,这是无效的,并产生未定义的行为

vector<node> children;

在这个数据成员声明的点上,类node是不完整的;它的大小还不知道。

不能将不完整的类型用作标准库容器的项类型(但可以使用指针)。


在析构函数实现中,还有

delete this;

产生Undefined Behavior,一个调用析构函数的无限递归,析构函数(在这个delete表达式中)调用自己,依此类推


数据成员声明

string& name;

它也有一种强烈的、令人不快的气味,但由于您没有显示构造函数的实现,我不能百分之百地肯定它是错误的。

然而,考虑到代码的其余部分,这是正确的可能性是无穷小的。只需使用

string name_;

通常,树使用在空闲存储上分配的节点。这意味着要贩运指向节点的指针,并删除不再使用的节点。问题中的代码没有遵循这个模型:它在堆栈上分配根节点,并在每个节点中存储节点对象而不是指针。有了这些代码,所有编译器生成的析构函数都可以正常工作。不需要任何用户定义的析构函数。