用于树结构的C ++析构函数

时间:2016-05-04 19:21:53

标签: c++ tree destructor

我有这种树结构:

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上执行<) / p>

到目前为止,除了析构函数之外,所有方法都正常工作。这是我的第一个析构函数,我想出了以下递归尝试,但不知道它为什么不能工作。

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;
}

结果是&#34;输入〜左子节点&#34;

的无限输出

3 个答案:

答案 0 :(得分:3)

  

“(我知道~tode()无论如何都会在主函数末尾的所有对象上运行,但我想确保它首先在根r上执行)”

这句话足以说明这个问题的所有内容都只是基于误解。

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

而是阅读更多关于析构函数,它们的调用以及它们的用途。

显式调用它不会抑制它的隐式调用。双重破坏是不明确的行为。

同样delete this是非常棘手的,需要你必须非常确定它意味着什么。

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

答案 1 :(得分:1)

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

vector<node> children;

在此数据成员声明时,类node 不完整;它的大小尚不清楚。

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

在析构函数实现中,也是

delete this;

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

数据成员声明

string& name;

也有一种强烈的,令人不快的气味,但由于你没有展示构造函数的实现,我不能断言100%它是错的。

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

string name_;

答案 2 :(得分:1)

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