Previous | Table of Contents | Next |
One of the things that most distinguish C and C++ from most other computer languages is their use of pointers. At first, pointers may seem difficult or exoticbut other languages use pointers all the time. The difference is that these other languages carry out pointer operations under the coversyou just dont see them. C and C++ are more transparent, and they give you more control.
What are pointers, anyway? Ill provide a more detailed description in the next section, but, in general, pointers are addresses: relatively small units of data (two bytes on 16-bit systems) that access other pieces of data indirectly. You can use an address to access an arbitrarily large chunk of data, often making significant gains in efficiency. In C and C++, pointers are closely related to arrays and character strings.
Pointers are, if anything, even more important in C++ than in C. C++ encourages the dynamic creation of objects through the use of the new operator, which returns a pointer. Moreover, certain operator functions (which Ill discuss in Chapter 7, Operator Overloading) require understanding of pointers. In this chapter, well focus on the use of pointers with parameters, strings, and arrays.
Simply stated, a pointer is a variable or an argument that stores an address in memory. Although this definition is technically complete, it is probably meaningless unless you understand what pointers are forthat is, how they are used. The important point is that, like a handle or a key, a pointer provides indirect access to data, and sometimes this arrangement is much more efficient than doing things the usual way.
Suppose you and I are two different functions (ok, I know that sounds silly, but stay with me on this) or, possibly, two separate objects. Suppose, further, that you have a large piece of data that you need to share with me. For example, you might need to pass me a long string of characters for me to display on the screen.
There are several possibilities for enabling this sharing of data. If the data structure is global, then sharing of data is automatic. But as I explained in Chapter 2, its best to use as few global variables as possible. So you frequently need to pass a data structure as an argument in a function call. This leaves two possibilities:
To visualize these scenarios, try to picture the computers stack, which is the area of memory reserved for passing data between functions. Passing a data structure directly causes an entire copy of the data to be placed on the stack. But passing an address causes a relatively small amount of data to be placed on the stack (typically, either two or four bytes, depending on the computers address size). As the function being called, I need only the location of the data structureits addressto gain access to all the data. Figure 3.1 illustrates these two approaches to passing data.
Figure 3.1 Passing data directly and passing its address (a pointer).
In the second scenario, I have only the address of the data. But this is all I need to access or modify the original data. Manipulating data through its address is called indirection. Modern processors are designed with a great deal of support for indirection.
The usefulness of pointers is not limited to saving memory on the stack. Among other things, pointers enable passing by reference, which is the topic well look at next.
If youve used Basic, FORTRAN, or Pascal, to name only a few common languages, youre probably familiar with passing by reference and passing by value: a function can permanently change the value of an argument only if you pass by reference.
With languages such as Basic and FORTRAN, passing by reference is automatic or easily controlled by a simple keyword (such as var in Pascal). You may not have realized it, but these languages pass a pointer when you pass by reference. The language hides this fact from you, so you dont have to learn pointer syntax, as required by C.
![]() | C++, but not C, provides a special reference operator (&) that lets you use the same high-level pass-by-reference technique that Basic, FORTRAN, and Pascal support. This operator is introduced in Chapter 6, Another Look at Constructors. However, its best to learn first how to pass by reference the hard way: with pointers. Even with C++, sooner or later you have to use pointers, and the best way to learn is to start with passing by reference. |
The connection between pointers and passing by reference should be clear if you look at Figure 3.1 again. If you pass by value, I get a complete copy of the original data. I can change the copy as much as I want, but this has no effect on the original data. When I finish execution, all the stack area Ive been using is released. None of the changes I made to my copy have any effect on the program.
If, however, I get a pointer to your data, then changes I make affect you. A pointer is not exactly a new piece of data but instead is something that tells me the location of your data, which enables me to change it. Its as if you gave me the location and combination of the file cabinet containing your original records rather than make separate copies for me.
Therefore, passing a pointer (an address) is the same as passing by reference. In fact, thats literally what passing by reference means: a pointer refers to the original copy of the data.
To use pointers to pass by reference, you need to follow several steps:
The rest of this section discusses each of these steps in a more detail.
Previous | Table of Contents | Next |