On the Sentinel Node wikipedia page it says that the benefits of a sentinel node over NULL are :
I will try to answer in the context of the standard template library:
1) In a call to "next()", NULL does not necessarily indicate end-of-list. What if a memory error occurred? Returning a sentinel node, is a definitive way to indicate that end-of-list had occurred, and not some other outcome. In other words, NULL could indicate a variety of things, not just end-of-list.
2) This is just one possible method: when you create your list, create a private node that is not shared outside of the class (called "lastNode" for instance). Upon detecting that you have iterated to the end of the list, have "next()" return a reference to "lastNode". Also have a method called "end()" return a reference to "lastNode". Lastly, depending on how you implement your class, you might need to override the comparison operator for this to work properly.
Example:
class MyNode{
};
class MyList{
public:
MyList () : lastNode();
MyNode * next(){
if (isLastNode) return &lastNode;
else return //whatever comes next
}
MyNode * end() {
return &lastNode;
}
//comparison operator
friend bool operator == (MyNode &n1, MyNode &n2){
return (&n1 == &n2); //check that both operands point to same memory
}
private:
MyNode lastNode;
};
int main(){
MyList list;
MyNode * node = list.next();
while ( node != list.end() ){
//do stuff!
node = list.next();
}
return 0;
}