228 Chapter 5 / Linked Lists: Const Node C
228 Chapter 5 / Linked Lists: Const Node C
pointer c cannot be used to change the node. To be precise, for the declaration
const node *c :
1. You might think that the const keyword prevents c from moving around
and pointing to different nodes. That is wrong. The pointer c can move
and point to many different nodes, but we are forbidden from using c to
change any of those nodes that c points to. (If you should wish to create a
pointer that can be set once during its definition and never changed to
point to a new object, then put the word const after the *. For example:
node *const c = &first; .)
2. Because of the const keyword, you might think that the node that c
points to can never be changed by any means. That’s not quite right either.
Why not? The reason is that we might have another ordinary pointer that
points to the same node that c points to. In that case, the node could be
changed by accessing it through the ordinary pointer. The const keyword
only prevents changing the node by accessing it through c.
3. To enforce the const rule, the C++ compiler permits a pointer such as
c to activate only constant member functions. For example, with our
declaration of c as const node *c , we can activate c->data( ), but
c->set_data( ) is forbidden.
The third rule is a good one, but for applications such as linked lists, the rule of
the C++ compiler doesn’t go quite far enough. We recommend an additional
programming tip that increases reliability:
PROGRAMMING TIP
A RULE FOR A NODE’S CONSTANT MEMBER FUNCTIONS
A node’s constant member functions should never provide a result that could later
be used to change any part of the linked list. This increases reliability because we
can clearly see which functions have the possibility of causing an alteration to the
underlying data structure.
providing a Our programming tip has a surprising effect: We must sometimes write two
const version similar versions of the same member function. For example, the purpose of the
and a non-const link member function is to obtain a copy of a node’s link field. At first glance,
version of a this sounds like a constant member function, since retrieving a member variable
function does not change an object. We might write this:
node* link( ) const { return link_field; }
WARNING!
This link This implementation does compile, but it violates our programming tip about
implementation constant member functions. For example, suppose we have this list set up:
has a bug!
1.6 3.0
head_ptr NULL
A Fundamental Node Class for Linked Lists 229
Using the constant member function, link, we can execute two statements that
change the data in one of the nodes:
node *second = head_ptr->link( );
1.6 3.0
head_ptr NULL
second
After this statement, the data in the second node is now 9.2:
1.6 9.2
head_ptr NULL
second
This is a bad situation because the node’s constant member functions should
never provide a result that we can later use to change any part of the linked list.
With this in mind, it makes sense to implement link as a non-constant member
function. Making the function non-constant provides better accuracy about how
the function’s results might be used. So, we will implement link as a non-
constant member function, like this:
node* link( ) { return link_field; }
FIGURE 5.10 Header File for the Node Class and the Linked-List Toolkit
A Header File
// FILE: node1.h (part of the namespace main_savitch_5)
// PROVIDES: A class for a node in a linked list and a collection of functions for
// manipulating linked lists
//
// TYPEDEF for the node class:
// Each node of the list contains a piece of data and a pointer to the next node. The
// type of the data is defined as node::value_type in a typedef statement. The value_type
// may be any of the C++ built-in types (int, char, etc.), or a class with a default constructor,
// a copy constructor, an assignment operator, and a test for equality.
//
// CONSTRUCTOR for the node class:
// node(const value_type& init_data, node* init_link)
// Postcondition: The node contains the specified data and link.
// NOTE: The init_data parameter has a default value that is obtained from the default
// constructor of the value_type. In the ANSI/ISO Standard, this notation is also allowed
// for the built-in types, providing a default value of zero. The init_link has a default
// value of NULL. (continued)
A Linked-List Toolkit 255
// NOTE:
// Some of the functions have a return value that is a pointer to a node. Each of these
// functions comes in two versions: a non-const version (where the return value is node* )
// and a const version (where the return value is const node* ).
// EXAMPLES:
// const node *c;
// c->link( ) activates the const version of link
// list_search(c, ... calls the const version of list_search
// node *p;
// p->link( ) activates the non-const version of link
// list_search(p, ... calls the non-const version of list_search
//
// MEMBER FUNCTIONS for the node class:
// void set_data(const value_type& new_data)
// Postcondition: The node now contains the specified new data.
//
// void set_link(node* new_link)
// Postcondition: The node now contains the specified new link.
//
// value_type data( ) const
// Postcondition: The return value is the data from this node.
//
// const node* link( ) const <----- const version
// and
// node* link( ) <----- non-const version
// See the previous note about the const version and non-const versions.
// Postcondition: The return value is the link from this node.
//
// FUNCTIONS in the linked-list toolkit:
// size_t list_length(const node* head_ptr)
// Precondition: head_ptr is the head pointer of a linked list.
// Postcondition: The value returned is the number of nodes in the linked list.
//
// void list_head_insert(node*& head_ptr, const node::value_type& entry)
// Precondition: head_ptr is the head pointer of a linked list.
// Postcondition: A new node containing the given entry has been added at the head of
// the linked list; head_ptr now points to the head of the new, longer linked list.
//
// void list_insert(node* previous_ptr, const node::value_type& entry)
// Precondition: previous_ptr points to a node in a linked list.
// Postcondition: A new node containing the given entry has been added after the node
// that previous_ptr points to.
//
(continued)
256 Chapter 5 / Linked Lists
(continued)