C Archives

Chapter 10 - Using Pointers

Visual C++ 6: The Complete Reference
Chris H. Pappas and William H. Murray, III
  Copyright 1998 The McGraw-Hill Companies

The C++ Reference Type
C++ provides a form of call-by-reference that is even easier to use than pointers. First, let’s examine the use of reference variables in C++. As with C, C++ enables you to declare regular variables or pointer variables. In the first case, memory is actually allocated for the data object; in the second case, a memory location is set aside to hold an address for an object that will be allocated at another time. C++ has a third kind of declaration, the reference type. Like a pointer variable, a reference variable refers to another variable location, but like a regular variable, it requires no special dereferencing operators. The syntax for a reference variable is straightforward:
int iresult_a=5;
int& riresult_a=iresult_a; // valid
int& riresult_b;           // invalid: uninitialized
This example sets up the reference variable riresult_a and assigns it to the existing variable iresult_a. At this point, the referenced location has two names associated with it—iresult_a and riresult_a. Because both variables point to the same location in memory, they are, in fact, the same variable. Any assignment made to riresult_a is reflected through iresult_a; the inverse is also true, and changes to iresult_a occur through any access to riresult_a. Therefore, with the reference data type, you can create what is sometimes referred to as an alias for a variable.
The reference type has a restriction that serves to distinguish it from pointer variables, which, after all, do something very similar. The value of the reference type must be set at declaration, and it cannot be changed during the run of the program. After you initialize this type in the declaration, it always refers to the same memory location. Therefore, any assignments you make to a reference variable change only the data in memory, not the address of the variable itself. In other words, you can think of a reference variable as a pointer to a constant location.
For example, using the preceding declarations, the following statement doubles the contents of iresult_a by multiplying 5 * 2:
riresult_a *= 2;
The next statement assigns icopy_value (assuming it is of type int) a copy of the value associated with riresult_a:
icopy_value = riresult_a;
The next statement is also legal when using reference types:
int *piresult_a = &riresult_a;
This statement assigns the address of riresult_a to the int * variable piresult_a.
The primary use of a reference type is as an argument or a return type of a function, especially when applied to user-defined class types (see Chapter 15).
Functions Returning Addresses
When you return an address from a function using either a pointer variable or a reference type, you are giving the user a memory address. The user can read the value at the address, and if you haven’t declared the pointer type to be const, the user can always write the value. By returning an address, you are giving the user permission to read and, for non-const pointer types, write to private data. This is a significant design decision. See if you can anticipate what will happen in this next program:
//
//  refvar.cpp
//  A C++ program showing what NOT to do with address
//  variables
//  Copyright (c) Chris H. Pappas and William H. Murray, 1998
//

#include <iostream.h>

int
*ifirst_function(void);
int
*isecond_function(void);

void main( )
{
 int
*pi=ifirst_function( );
 isecond_function( );
 cout << “Correct value? ” <<
*pi;
}
int *ifirst_function(void)
{
 int ilocal_to_first=11;
 return &ilocal_to_first;
}

int
*isecond_function(void)
{
 int ilocal_to_second=44;
 return &ilocal_to_second;
}
Using the Integrated Debugger
To examine the operation of this C++ code while it is actually working, you can use the integrated debugger. Use the Variables window to keep an eye on the variable pi.
What has happened? When the ifirst_function( ) is called, local space is allocated on the stack for the variable ilocal_to_first, and the value 11 is stored in it. At this point the ifirst_function( ) returns the address of this local variable (very bad news). The second statement in the main program invokes the isecond_function( ). isecond_function( ) in turn allocates local space for ilocal_to_second and assigns it a value of 44. So how does the printf statement print a value of 44 when it was passed the address of ilocal_to_first when ifirst_function( ) was invoked?
What happened was this. When the address of the itemporary local variable ilocal_to_first was assigned to pi by ifirst_function( ), the address to the itemporary location was retained even after ilocal_to_first went out of scope. When isecond_function() was invoked, it also needed local storage. Since ilocal_to_first was gone, ilocal_to_second was given the same storage location as its predecessor. With pi hanging onto this same busy memory cell, you can see why printing the value it now points to yields a 44. Extreme care must be taken not to return the addresses of local variables.

Books24x7.com, Inc 2000 –  


Visual C++ 6(c) The Complete Reference
Visual Studio 6: The Complete Reference
ISBN: B00007FYGA
EAN: N/A
Year: 1998
Pages: 207

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net