I have a class called "node". I link a bunch of node objects together to form a linked list. When the "node" destructor is called, it only deletes the first node. How do I iterate through the entire linked list of nodes and delete each node object?
Here is the class definition:
class Node
{
private:
double coeff;
int exponent;
Node *next;
public:
Node(double c, int e, Node *nodeobjectPtr)
{
coeff = c;
exponent = e;
next = nodeobjectPtr;
}
~Node()
{
printf("Node Destroyed");
}
The destructor is called by invoking delete on the pointer to the first node of the linked node list.
Since you don't know how many nodes there are in a list, if you do not have firm bounds on that it's not a good idea to invoke destructors recursively, because each call uses some stack space, and when available stack space is exhausted you get Undefined Behavior, like a crash.
So if you absolutely want to do deallocate following nodes in a node's destructor, then it has to first unlink each node before destroying it.
It can go like this:
Node* unlink( Node*& p )
{
Node* result = p;
p = p->next;
result->next = nullptr;
return result;
}
Node::~Node()
{
while( next != nullptr )
{
delete unlink( next );
}
}
But better, make a List
object that has ownership of the nodes in a linked list.
Of course, unless this is for learning purposes or there is a really good reason to roll your own linked list, just use a std::vector
(and yes I mean that, not std::list
).
How do I iterate through the entire linked list of nodes and delete each node object?
It would be cleaner if you had a separate class to manage the entire list, so that nodes can be simple data structures. Then you just need a simple loop in the list's destructor:
while (head) {
Node * victim = head;
head = victim->next; // Careful: read this before deleting
delete victim;
}
If you really want to delegate list management to the nodes themselves, you'll need to be a bit more careful:
while (next) {
Node * victim = next;
next = victim->next;
victim->next = nullptr; // Careful: avoid recursion
delete victim;
}
Under this scheme, you'll also need to be careful when deleting a node after removing it from the list - again, make sure you reset its pointer so it doesn't delete the rest of the list. That's another reason to favour a separate "list" class.