8.4 Pass-by-Reference with Pointers

There are three ways in C++ to pass arguments to a function:

  • pass-by-value

  • pass-by-reference with a reference argument

  • pass-by-reference with a pointer argument.

Chapter 6 compared and contrasted the first two. Here, we explain pass-by-reference with a pointer argument.

Chapter 6 showed that return can return one value from a called function or simply return control. You also learned that arguments can be passed to a function using reference parameters, which enable the called function to modify the original values of the arguments in the caller. Reference parameters also enable programs to pass large data objects to a function without the overhead of pass-by-value which, of course, copies the object. Pointers, like references, also can be used to modify variables in the caller or to pass large data objects by reference to avoid the overhead of copying the objects.

You can use pointers and the indirection operator (*) to accomplish pass-by-reference (exactly as pass-by-reference is done in C programs—C does not have references). When calling a function with a variable that should be modified, the address of the variable is passed. This is normally accomplished by applying the address operator (&) to the name of the variable whose value will be modified.

An Example of Pass-By-Value

Figures 8.6 and 8.7 present two versions of a function that cubes an integer. Figure 8.6 passes variable number by value (line 12) to function cubeByValue (lines 17–19), which cubes its argument and passes the result back to main using a return statement (line 18). The new value is assigned to number (line 12) in main. The calling function has the opportunity to examine the function call’s result before modifying variable number’s value. For example, we could have stored the result of cubeByValue in another variable, examined its value and assigned the result to number only after determining that the returned value was reasonable.

Fig. 8.6 Pass-by-value used to cube a variable’s value.

Alternate View

 1   // Fig. 8.6: fig08_06.cpp
 2   // Pass-by-value used to cube a variable’s value.
 3   #include <iostream>
 4   using namespace std;
 5
 6   int cubeByValue(int); // prototype
 7
 8   int main() {
 9      int number{5};
10
11      cout << "The original value of number is " << number;
12      number = cubeByValue(number); // pass number by value to cubeByValue   
13      cout << "
The new value of number is " << number << endl;
14   }
15
16   // calculate and return cube of integer argument               
17   int cubeByValue(int n) {                                       
18      return n * n * n; // cube local variable n and return result
19   }                                                              

The original value of number is 5
The new value of number is 125

An Example of Pass-By-Reference with Pointers

Figure 8.7 passes the variable number to function cubeByReference using pass-by-reference with a pointer argument (line 13)—the address of number is passed to the function. Function cubeByReference (lines 18–20) specifies parameter nPtr (a pointer to int) to receive its argument. The function uses the dereferenced pointer—*nPtr, an alias for number in main—to cube the value to which nPtr points (line 19). This directly changes the value of number in main (line 10). Line 19 can be made clearer with redundant parentheses:


*nPtr = (*nPtr) * (*nPtr) * (*nPtr); // cube *nPtr

Fig. 8.7 Pass-by-reference with a pointer argument used to cube a variable’s value.

Alternate View

 1   // Fig. 8.7: fig08_07.cpp
 2   // Pass-by-reference with a pointer argument used to cube a
 3   // variable’s value.
 4   #include <iostream>
 5   using namespace std;
 6
 7   void cubeByReference(int*); // prototype
 8
 9   int main() {
10      int number{5};
11
12      cout << "The original value of number is " << number;
13      cubeByReference(&number); // pass number address to cubeByReference   
14      cout << "
The new value of number is " << number << endl;
15    }
16
17    // calculate cube of *nPtr; modifies variable number in main
18    void cubeByReference(int* nPtr) {                           
19       *nPtr = *nPtr * *nPtr * *nPtr; // cube *nPtr                
20    }                                                           

The original value of number is 5
The new value of number is 125

A function receiving an address as an argument must define a pointer parameter to receive the address. For example, the header for function cubeByReference (line 18) specifies that cubeByReference receives the address of an int variable (i.e., a pointer to an int) as an argument, stores the address in nPtr and does not return a value.

Function cubeByReference’s prototype (line 7) contains int* in parentheses. As with other types, it isn’t necessary to include the names of pointer parameters in prototypes— parameter names included for documentation purposes are ignored by the compiler.

Insight: Pass-By-Reference with a Pointer Actually Passes the Pointer By Value

Passing a variable by reference with a pointer does not actually pass anything by reference— a pointer to that variable is passed by value and is copied into the function’s corresponding pointer parameter. The called function can then access that variable in the caller simply by dereferencing the pointer, thus accomplishing pass-by-reference.

Graphical Analysis of Pass-By-Value and Pass-By-Reference

Figures 8.88.9 analyze graphically the execution of Fig. 8.6 and Fig. 8.7, respectively. In the diagrams, the values in rectangles above a given expression or variable represent the value of that expression or variable. Each diagram’s right column shows functions cubeBy-Value (Fig. 8.6) and cubeByReference (Fig. 8.7) only when they’re executing.

Fig. 8.8 Pass-by-value analysis of the program of Fig. 8.6.

  1. Step 1: Before main calls cubeByValue:

  2. Step 2: After cubeByValue receives the call:

  3. Step 3: After cubeByValue cubes parameter n and before cubeByValue returns to main:

  4. Step 4: After cubeByValue returns to main and before assigning the result to number:

  5. Step 5: After main completes the assignment to number:

Fig. 8.9 Pass-by-reference analysis of the program of Fig. 8.7.

  1. Step 1: Before main calls cubeByReference:

  2. Step 2: After cubeByReference receives the call and before *nPtr is cubed:

  3. Step 3: Before*nPtr is assigned the result of the calculation 5 * 5 * 5:

  4. Step 4: After *nPtr is assigned 125 and before program control returns to main:

  5. Step 5: After cubeByReference returns to main:

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset