Passing Function Arguments by Reference

In Hour 5, “Functions,” you learned that functions have two limitations: Arguments are passed by value, and the return statement can return only one value.

Passing values to a function by reference can overcome both of these limitations. In C++, passing by reference is accomplished in two ways: using pointers and using references. The syntax is different, but the net effect is the same: Rather than a copy being created within the scope of the function, the actual original object is passed into the function.

Passing an object by reference enables the function to change the object being referred to.

Listing 11.4 creates a swap function and passes in its parameters by value.

Listing 11.4. Demonstrating Pass by Value
 0:  //Listing 11.4 Demonstrates passing by value
 1:  #include <iostream>
 2:
 3:  void swap(int x, int y);
 4:
 5:  int main()
 6:  {
 7:      int x = 5, y = 10;
 8:
 9:      std::cout << "Main. Before swap, x: " << x
10:                                  << " y: " << y << "
";
11:      swap(x,y);
12:      std::cout << "Main. After swap, x: " << x
13:                                  << " y: " << y << "
";
14:      return 0;
15:  }
16:
17:  void swap (int x, int y)
18:  {
19:      int temp;
20:
21:      std::cout << "Swap. Before swap, x: " << x
22:                                  << " y: " << y << "
";
23:
24:      temp = x;
25:      x = y;
26:      y = temp;
27:
28:      std::cout << "Swap. After swap, x: " << x
29:                                 << " y: " << y << "
";
30:
31:  }


Main. Before swap. x: 5 y: 10
Swap. Before swap. x: 5 y: 10
Swap. After swap. x: 10 y: 5
Main. After swap. x: 5 y: 10
					

This program initializes two variables in main() and then passes them to the swap() function, which appears to swap them. But when they are examined again in main(), they are unchanged!


The problem here is that x and y are being passed to swap() by value. That is, local copies were made in the function. What you want is to pass x and y by reference.

There are two ways to solve this problem in C++: You can make the parameters of swap() pointers to the original values, or you can pass in references to the original values.

Making swap() Work with Pointers

When you pass in a pointer, you pass in the actual address of the object, and thus the function can manipulate the value at that address. To make swap() change the actual values using pointers, the function, swap(), should be declared to accept two int pointers. Then, by dereferencing the pointers, the values of x and y will, in fact, be swapped. Listing 11.5 demonstrates this idea.

Listing 11.5. Passing by Reference Using Pointers
 0:  //Listing 11.5 Demonstrates passing by reference
 1:  #include <iostream>
 2:
 3:  void swap(int *x, int *y);
 4:
 5:  int main()
 6:  {
 7:      int x = 5, y = 10;
 8:
 9:      std::cout << "Main. Before swap, x: " << x
10:                                  << " y: " << y << "
";
11:      swap(&x,&y);
12:      std::cout << "Main. After swap, x: " << x
13:                                 << " y: " << y << "
";
14:      return 0;
15:  }
16:
17:  void swap (int *px, int *py)
18:  {
19:      int temp;
20:
21:      std::cout << "Swap. Before swap, *px: " << *px
22:                                  << " *py: " << *py << "
";
23:
24:      temp = *px;
25:      *px = *py;
26:      *py = temp;
27:
28:      std::cout << "Swap. After swap, *px: " << *px
29:                                 << " *py: " << *py << "
";
30:  }


Main. Before swap. x: 5 y: 10
Swap. Before swap. *px: 5 *py: 10
Swap. After swap. *px: 10 *py: 5
Main. After swap. x: 10 y: 5
						

Success! On line 3, the prototype of swap() is changed to indicate that its two parameters will be pointers to int rather than int variables. When swap() is called on line 11, the addresses of x and y are passed as the arguments.


On line 19, a local variable, temp, is declared in the swap() function. Temp need not be a pointer; it will just hold the value of *px (that is, the value of x in the calling function) for the life of the function. After the function returns, temp will no longer be needed.

On line 24, temp is assigned the value at px. On line 25, the value at px is assigned to the value at py. On line 26, the value stashed in temp (that is, the original value at px) is put into py.

The net effect of this is that the values in the calling function, whose address was passed to swap(), are in fact swapped.

Implementing swap() with References

The preceding program works, but the syntax of the swap() function is cumbersome in two ways. First, the repeated need to dereference the pointers within the swap() function makes it error-prone and hard to read. Second, the need to pass the address of the variables in the calling function makes the inner workings of swap() overly apparent to its users.

It is a goal of C++ to prevent the user of a function from worrying about how it works. Passing by pointers puts the burden on the calling function which is not where it belongs. The calling function must know to pass in the address of the object it wants to swap.

The burden of understanding the reference semantics should be on the function implementing the swap. To accomplish this, you use references. Listing 11.6 rewrites the swap() function using references. Now the calling function just passes in the object, and because the parameters are declared to be references, the semantics are pass by reference. The calling function doesn't need to do anything special.

Listing 11.6. swap() Rewritten with References
 0:  //Listing 11.6 Demonstrates passing by reference
 1:  // using references!
 2:  #include <iostream>
 3:
 4:  void swap(int &x, int &y);
 5:
 6:  int main()
 7:  {
 8:      int x = 5, y = 10;
 9:
10:      std::cout << "Main. Before swap, x: " << x
11:                                  << " y: " << y << "
";
12:      swap(x,y);
13:      std::cout << "Main. After swap, x: " << x
14:                                 << " y: " << y << "
";
15:      return 0;
16:  }
17:
18:  void swap (int &rx, int &ry)
19:  {
20:      int temp;
21:
22:      std::cout << "Swap. Before swap, rx: " << rx
23:                                  << " ry: " << ry << "
";
24:
25:      temp = rx;
26:      rx = ry;
27:      ry = temp;
28:
29:      std::cout << "Swap. After swap, rx: " << rx
30:                                 << " ry: " << ry << "
";
31:  }


Main. Before swap, x:5 y: 10
Swap. Before swap, rx:5 ry:10
Swap. After swap, rx:10 ry:5
Main. After swap, x:10, y:5
						

Just as in the example with pointers, two variables are declared on line 8, and their values are printed on lines 10 and 11. On line 12 the function swap() is called, but note that x and y are passed, not their addresses. The calling function simply passes the variables.


When swap() is called, program execution jumps to line 18, where the variables are identified as references. Their values are printed on lines 22 and 23, but note that no special operators are required. These are aliases for the original values, and can be used as such.

On lines 25–27 the values are swapped, and then they're printed on lines 29 and 30. Program execution jumps back to the calling function, and on lines 13 and 14 the values are printed in main(). Because the parameters to swap() are declared to be references, the values from main() are passed by reference, and thus are changed in main() as well.

References provide the convenience and ease of use of normal variables, with the power and pass-by-reference capability of pointers!

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

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