Page excerpted from Pass by Reference topic of a first year course in Structured Programming
A Swap Function
Consider the following highly desirable swap function:
Code Notes
1. Since variables are basically data containers that can only
hold one piece of data at a time arg1
and arg2
can't just be swapped directly.
2. Instead, a 3rd container hold
is created, then
the piece of data from one of the two variables is copied to it(in this case arg1
but
it wouldn't matter which one was started with).
3. Then the data from arg2
is copied to arg1
, over-writing arg1
's
original data!
4. Fortunately, arg1
's data has been preserved in in hold
so
now that data is copied back into arg2
, completing the exchange.
The idea behind this swap routine is that it swaps the values of a pair of variables around. Swap routines are widely used. As we will find out, all routines to sort data into some sort of order work by comparing two pieces of data and, if they are out of order, swapping them.
If you were to run the routine in the TM you will find the swapping works just fine.
The only problem is, nothing happens from the calling routine's perspective. Here it is. Let's run it.
Code Notes
1. Step into main to the call to intSwap(a,b)
. The call should be loaded in the Expression Engine
2. Step through the call in the Expression Engine. Notice how a
and b
are replaced by their values.
3. Once the intSwap
routine itself is reached, switch back to the source window and step through the parameter initialization. The
parameters
arg1
and arg2
are effectively both local variables belonging to the intSwap
routine. They are initialized to the values passed in by the call. arg1
gets the first value, 5
, and arg2
the second value, 3
.
4. Step through the swap and observe the values in arg1
and arg2
swap perfectly.
5. Returning from intSwap
, arg1
and arg2
go out of scope. a
and b
are untouched. The function hasn't affected them.
C passes by value so arg1
and arg2
are a copy of
the original variables. As soon as we leave the intSwap
routine arg1
and arg2
disappear
and the original x1
and x2
are unchanged.As we saw,
the intSwap
function merrily swaps arg1
and arg2,
but x1
and x2
are
untouched because arg1
is a copy of x1
and arg2
is
a copy of x2
!
In the case of the factorial
function, this behaviour was a desirable security
feature.
Now suddenly it's a bug. How can we get around it?
Pass-by-Reference
C++ inherited C's pass-by-value design. But C++ added a new feature known as pass-by-reference to allow a function to access calling variables.
Here's a new version of the intSwap
function that uses this pass-by-reference technique. The type of each parameter has been modified by adding an ampersand (&)
, technically known as a reference modifier.
Code Notes
1. Step into main to the call to intSwap(a,b)
. The call should be loaded in the Expression Engine
2. Step through the call in the Expression Engine. Now a
and b
turn blue to indicate a refernce to them is about to be passed.
3. Once the intSwap
routine itself is reached, switch back to the source window and step through the parameter initialization. The
parameters
arg1
and arg2
are effectively both local variables belonging to the intSwap
routine. They are initialized to the values passed in by the call. arg1
gets the first value, 5
, and arg2
the second value, 3
.
4. Step through the swap and observe the values in arg1
and arg2
swap perfectly.
5. Returning from intSwap
, arg1
and arg2
go out of scope. a
and b
are untouched. The function hasn't affected them.
The only thing that has changed is the declaration of the two function parameters .
Now, instead of arg1
and arg2
being int
s,
they are formally called reference
s to int
s. In the
syntax of C++ a reference to int
(or reference
to double
or reference to char
) is a
distinctly different type from an int
(or double
or char
).
The variables are the function parameters and they are references to the original variables.
Note that the call to the pass-by-reference (useful) version of the intSwap
function
is identical to the (useless) pass-by-value version.
Notice, there is no way you can tell by looking at a call whether the arguments are being passed by value or by reference. You have to look at the function declaration to know.
void intSwap(int& x1, int& x2);
is the declaration for a function that passes its arguments by reference while
int factorial(int n);
is the declaration for a function that passes its arguments by value.
It should be noted that although the Teaching Machine supports windows into different types of memory (e.g. the heap) the instructor of this beginning course has configured the TM only to show the stack and has relabelled it as simply "memory". See shallow vs deep copy and linked lists for other instructor generated configurations.
Examples Shown in Full