二分搜索树析构函数
致力于用 C++ 实现我自己的 BST,以获得处理此类结构的经验。
我在实现析构函数时遇到了麻烦。我在我的研究中发现,一个人不能真正拥有递归析构函数(由于一个标志不允许在调用后在同一个对象上调用析构函数),但我不太确定其他方法可以成功清理树中的所有节点。
为了补偿,我创建了一个辅助函数 - 但是这会在“delete n”行上引发未解决的外部错误。有什么建议吗?
代码:
void BinSearchTree::Clear(tNode* n)
{
if (n->left != NULL)
Clear(n->left);
if (n->right != NULL)
Clear(n->right);
delete n;
n = NULL;
size--;
}
Working on implementing my own BST in C++ for the experience of dealing with such structures.
I've had trouble implementing a destructor. I found in my studies, that one can't really have a recursive destructor (due to a flag that doesn't allow the destructor to be called on the same object after having been called), but I'm not really sure of any other way to successfully clean up all the nodes in the tree.
To compensate, I've created a helper function - however this throws an unresolved external error on the 'delete n' line. Any tips?
Code:
void BinSearchTree::Clear(tNode* n)
{
if (n->left != NULL)
Clear(n->left);
if (n->right != NULL)
Clear(n->right);
delete n;
n = NULL;
size--;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
你可以有一个递归析构函数;你不能做的是两次删除同一个对象。
在 C++ 中删除树的典型方法可能是这样的:
关于未解决的外部错误 - 当您尝试编译/链接程序时是否抛出该错误?如果是这样,可能是因为 tNode 类的代码(特别是 tNode 析构函数,如果您声明了的话)不存在或没有编译到您的项目中。
You can have a recursive destructor; what you can't do is delete the same object twice.
A typical way to delete a tree in C++ might be something like this:
Regarding the unresolved external error -- is that error thrown when you try to compile/link the program? If so, it's probably because the code for the tNode class (and in particular the tNode destructor, if you declared one) doesn't exist or isn't getting compiled into your project.
之前的答案指出,未解决的外部错误可能是由链接器可以看到的翻译单元中声明但未定义的 tNode 析构函数引起的。
但是,您遇到了第二个错误:您似乎认为将 n 设置为 null 会执行一些实际无法执行的操作。指针值n 按值传递,而不是按引用传递,因此更改其值(例如通过分配NULL)在函数返回后不会产生任何影响。
当您清除树并期望根节点指针已设置为 NULL(此时它仍然是指向已释放内存的悬空指针)时,这可能会给您带来错误。结果将是运行时错误,而不是链接器错误。
会做你所期望的。
Previous answers have pointed out that the unresolved external error is likely caused by a tNode destructor that is declared but not defined in a translation unit that the linker can see.
However, you have a second error: You appear to believe that setting n to null does something it doesn't do. The pointer value n is passed by value, not by reference, such that changing its value (e.g. by assigning NULL) has no effect after the function returns.
This will probably give you errors when you clear the tree and expect the root node pointer to have been set to NULL, when it remains a dangling pointer to freed memory. The result will be runtime error, not your linker error.
Will do what you expect.
问题是,在您的类中,您可能声明节点结构具有自定义析构函数,但您没有提供它,因此在链接时编译器会抱怨缺少一块。
如果您不需要在析构函数中添加任何自定义代码,那么您只需从结构声明中删除析构函数,您的程序就可以正常编译。
但请注意,使用析构函数来销毁子节点完全没有问题(请参阅 Brendan Long 答案)。如果您在尝试时遇到问题,那么您遇到的问题一定是其他问题。
The problem is that in you class you probably declared that the node structure has a custom destructor, but you don't provide it so at link time the compiler is complaining a piece is missing.
If you don't need any more custom code in the destructor then you can just remove the destructor from the struct declaration and your program will compile fine.
Note however that there is no problem at all to have a destructor of to destory children nodes (see Brendan Long answer). If you ran into problems while attempting that the issue you faced must me something else.
只需使用析构函数。听起来你的问题是你试图直接调用析构函数,但语言会为你处理这个问题。当您离开堆栈分配对象的范围或删除对象时,将调用它们。
您所需要的只是:
delete
将调用它们的析构函数。注意:
删除 NULL
是完全安全的,它 没有效果。Just use a destructors. It sounds like your problem is that you were trying to call the destructors directly, but the language handles this for you. They're called either when you leave a stack allocated object's scope, or when you delete an object.
All you should need is this:
delete
will call their destructors.Note: It's perfectly safe to
delete NULL
, it has no effect.自动化怎么样:
现在破坏是自动的。 :-)
How about automating it:
Now destruction is automatic. :-)
也可以使用递归,只需要将函数头改为:
即可。
You can also use recursion, you just need to change the function header to:
and it will work.