References as Function Parameters

Most often, references are used as function parameters, making a variable name in a function an alias for a variable in the calling program. This method of passing arguments is called passing by reference. Passing by reference allows a called function to access variables in the calling function. C++’s addition of the feature is a break from C, which only passes by value. Passing by value, recall, results in the called function working with copies of values from the calling program (see Figure 8.2). Of course, C lets you get around the passing by value limitation by using pointers.

Figure 8.2. Passing by value and passing by reference.

Image

Let’s compare using references and using pointers in a common computer problem: swapping the values of two variables. A swapping function has to be able to alter values of variables in the calling program. That means the usual approach of passing variables by value won’t work because the function will end up swapping the contents of copies of the original variables instead of the variables themselves. If you pass references, however, the function can work with the original data. Alternatively, you can pass pointers in order to access the original data. Listing 8.4 shows all three methods, including the one that doesn’t work, so that you can compare them.

Listing 8.4. swaps.cpp


// swaps.cpp -- swapping with references and with pointers
#include <iostream>
void swapr(int & a, int & b);   // a, b are aliases for ints
void swapp(int * p, int * q);   // p, q are addresses of ints
void swapv(int a, int b);       // a, b are new variables
int main()
{
    using namespace std;
    int wallet1 = 300;
    int wallet2 = 350;

    cout << "wallet1 = $" << wallet1;
    cout << " wallet2 = $" << wallet2 << endl;

    cout << "Using references to swap contents: ";
    swapr(wallet1, wallet2);   // pass variables
    cout << "wallet1 = $" << wallet1;
    cout << " wallet2 = $" << wallet2 << endl;

    cout << "Using pointers to swap contents again: ";
    swapp(&wallet1, &wallet2); // pass addresses of variables
    cout << "wallet1 = $" << wallet1;
    cout << " wallet2 = $" << wallet2 << endl;

    cout << "Trying to use passing by value: ";
    swapv(wallet1, wallet2);   // pass values of variables
    cout << "wallet1 = $" << wallet1;
    cout << " wallet2 = $" << wallet2 << endl;
    return 0;
}

void swapr(int & a, int & b)    // use references
{
    int temp;

    temp = a;       // use a, b for values of variables
    a = b;
    b = temp;
}

void swapp(int * p, int * q)    // use pointers
{
    int temp;

    temp = *p;      // use *p, *q for values of variables
    *p = *q;
    *q = temp;
}

void swapv(int a, int b)        // try using values
{
    int temp;

    temp = a;      // use a, b for values of variables
    a = b;
    b = temp;
}


Here’s the output of the program in Listing 8.4:

wallet1 = $300 wallet2 = $350           << original values
Using references to swap contents:
wallet1 = $350 wallet2 = $300           << values swapped
Using pointers to swap contents again:
wallet1 = $300 wallet2 = $350           << values swapped again
Trying to use passing by value:
wallet1 = $300 wallet2 = $350           << swap failed

As you’d expect, the reference and pointer methods both successfully swap the contents of the two wallets, whereas the passing by value method fails.

Program Notes

First, note how each function in Listing 8.4 is called:

swapr(wallet1, wallet2);        // pass variables
swapp(&wallet1, &wallet2);      // pass addresses of variables
swapv(wallet1, wallet2);        // pass values of variables

Passing by reference (swapr(wallet1, wallet2)) and passing by value (swapv(wallet1, wallet2)) look identical. The only way you can tell that swapr() passes by reference is by looking at the prototype or the function definition. However, the presence of the address operator (&) makes it obvious when a function passes by address ((swapp(&wallet1, &wallet2)). (Recall that the type declaration int *p means that p is a pointer to an int and therefore the argument corresponding to p should be an address, such as &wallet1.)

Next, compare the code for the functions swapr() (passing by reference) and swapv() (passing by value). The only outward difference between the two is how the function parameters are declared:

void swapr(int & a, int & b)
void swapv(int a, int b)

The internal difference, of course, is that in swapr() the variables a and b serve as aliases for wallet1 and wallet2, so swapping a and b swaps wallet1 and wallet2. But in swapv(), the variables a and b are new variables that copy the values of wallet1 and wallet2, so swapping a and b has no effect on wallet1 and wallet2.

Finally, compare the functions swapr() (passing a reference) and swapp() (passing a pointer). The first difference is in how the function parameters are declared:

void swapr(int & a, int & b)
void swapp(int * p, int * q)

The second difference is that the pointer version requires using the * dereferencing operator throughout when the function uses p and q.

Earlier, I said you should initialize a reference variable when you define it. A function call initializes its parameters with argument values from the function call. So reference function arguments are initialized to the argument passed by the function call. That is, the following function call initializes the formal parameter a to wallet1 and the formal parameter b to wallet2:

swapr(wallet1, wallet2);

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

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