Reputation: 1191
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--;
}
Upvotes: 9
Views: 33843
Reputation: 1
You can also use recursion, you just need to change the function header to:
void remove(node*& root)
and it will work.
Upvotes: 0
Reputation: 264381
How about automating it:
class BinSearchTree
{
std::auto_ptr<tNode> left;
std::auto_ptr<tNode> right;
BinSearchTree(BinSearchTree const&);
BinSearchTree& operator=(BinSearchTree const&); // private
};
Now destruction is automatic. :-)
Upvotes: 1
Reputation: 1912
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.
void BinSearchTree::Clear(tNode **N)
{
tNode * n = *N;
if (n->left != NULL)
Clear(n->left);
if (n->right != NULL)
Clear(n->right);
delete n;
*N = NULL;
size--;
}
Will do what you expect.
Upvotes: 4
Reputation: 73051
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:
BinSearchTree::~BinSearchTree()
{
delete _rootNode; // will recursively delete all nodes below it as well
}
tNode::~tNode()
{
delete left;
delete right;
}
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.
Upvotes: 21
Reputation: 54242
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:
~BinSearchTree() {
delete left;
delete right;
}
delete
will call their destructors.
Note: It's perfectly safe to delete NULL
, it has no effect.
Upvotes: 2
Reputation: 114461
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.
Upvotes: 3