Reliable Software Logo

C++ In Action

Pointers

A pointer variable stores the memory address of an object (for instance, of a variable, an array, a function, an instance of a class, etc.). Using a pointer one can access the contents of the object it points to. In this sense a pointer acts just like a reference, it is an alias of some other object. There is, however, one big difference between a pointer and a reference. A pointer is not permanently attached to an object-- it can be moved. The programmer can change the pointer to point to another object. This is a very powerful feature and, at the same time, a very dangerous one. The majority of bugs involve, in one way or another, the use of pointers. In C++ (and C) we have the following types of pointers:

  • Uninitialized pointers,
  • Pointers to deallocated memory,
  • Pointers beyond the end of an array,
  • Pointers that think they point to something else,
  • Cross your fingers, knock on wood kind of pointers.

Obviously we don’t want to use such pointers. We want to use pointers that at all times point to what they think (and we think, and the next person thinks) they point to. And that requires a lot of discipline on the programmer’s part. Therefore the first rule of pointer use is:

Don’t use pointers unless there is no other way.

Use references instead, whenever possible. You’ll definitely avoid the problem of uninitialized pointers. The use of references gives you also the opportunity to fine tune the scope of objects and variables. References, unlike pointers, have to be initialized at the point of definition. If they are inside an object, you’ll have to define the object in the right spot. It must be created within the scope where the objects to be accessed by these references are available. That imposes a certain natural order of creation.

Another misuse of pointers, a heritage of C, is the use of pointers in place of array indexes. The old argument was that scanning an array using a pointer results in faster code. Not so with modern optimizing compilers. It turns out that a compiler is more likely to do some aggressive (but correct!) optimizations when the algorithm is expressed using indexes rather than pointers. So here goes another myth from the dark ages of computing. We’ll discuss this issue in more detail soon.

Finally, many C-programmers are used to combining pointers with error codes, that is using a null pointer as a sign of error. Although there are ways of faking "null references," they won’t be discussed in this book for obvious reasons (they are ugly hacks!). The solution is either to separate error codes from references, or to use exceptions (see the chapter on resource management) to signal abnormal conditions. Of course, there is nothing wrong with functions that return pointers by design and use the null-pointer trick to signal special conditions.

 

NextNext: Pointers and References