I have a Node
class. The members are an int id
, and a pointer to the next node: Node* next
. I implemented the constructor and destructor as follows:
#include <iostream>
class Node
{
public:
int id;
Node *next;
Node() : id(0), next(nullptr) {}
explicit Node(int id) : id(id), next(nullptr) {}
~Node() {
std::cout << (*this) << " destructed \n";
delete next;
next = nullptr;
}
friend std::ostream &operator<<(std::ostream &os, const Node &node) {
os << "Node(" << node.id << ")";
return os;
}
};
int main()
{
Node *node0;
Node *node1;
node0 = new Node(0);
node1 = new Node(1);
node0->next = node1;
delete node0; // outputs Node(0) destructed\nNode(1) destructed
node0 = nullptr;
std::cout << (nullptr == node0) << '\n'; // outputs 1
std::cout << (nullptr == node1) << '\n'; // outputs 0
std::cout << *node1 << " \n"; // outputs Node(8430)
return 0;
}
I thought node1
should already point to nullptr
since when calling the destructor for node0
, its next is deleted and point to nullptr
, but the output suggests that node1
is apparently Node(8430) and is not a nullptr
.
I know that when dereferencing a nullptr
it could result in undefined behavior. How can I modify this program so that after calling delete node0
, node1
can also become nullptr
?
What you expect is similar to this:
void foo(int* ptr) {
delete ptr;
ptr = nullptr;
}
int main() {
int * x = new int;
foo(x);
assert( x == nullptr); // NOPE !!
}
ptr
is a copy of x
. delete ptr
deletes the dynamically allocated int
. That does not affect the value of x
in any way. x
still has the same value after calling foo
. It just is not a valid pointer anymore. The address where it points holds no int
anymore.
Or even simpler:
int* a = new int;
int* b = a;
delete a;
a = nullptr;
assert( b == nullptr ); // NOPE !!!
Actually your misunderstanding can be traced back to an even simpler example:
int a = 42;
int b = a;
a = 0;
assert( b == 0); // NO !!
With pointers it is no different.
In your code node0->next = node1;
a copy of the pointer is made. Then in the destructor of node0
you delete the node pointed to by node0->next
but that has no effect on the pointer in main.
TL;DR: Do not confuse the pointer and the pointee. delete x
deletes the object pointed to by x
. If you copy a pointer you have two totally independent pointers that point to the same object, assigning nullptr
to one of them has no effect on the other.