C++ Notes: Function Reference Parameters
Reference parameters are useful in two cases:
- Change values. Use a reference parameter when you need to change
the value of an actual parameter variable in
the call. When a function computes only one
value it is considered a better style to return the value with the
return
statement. However, if a function
produces more than one value, it is common to use reference parameters
to return values, or a combination of the return value and reference parameters.
- Efficiency. To pass large structures more efficiently. This is especially
common for passing structs or class objects. If no changes are made to the
parameter, it is should be declared
const
.
Reference parameters pass an address, not a value
When you declare a reference parameter,
the function call will pass the memory address
of where the actual parameter, instead of copying the parameter value into
the formal parameter.
Declare reference parameters with a &
To indicate a reference parameter, an ampersand (&) is written
in the function prototype and header after the parameter type name.
For example,
void assign(int& to, int from) {
to = from; // Will change the actual parameter in the call.
}
has two parameters, to is a reference parameter as indicated
by the ampersand, and from is a value parameter. This ampersand
must be in both the prototype and the function header.
Example - Swap (bad solution)
Let's say you want to exchange the values in two arguments.
int a = 5;
int b = 10;
swap(a,b);
// If we want a=10
and b=5
as the result, how do we write the function?
Here's an example that does NOT work correctly, altho there
is no error message.
void swap(int x, int y) { // BAD BAD BAD BAD BAD BAD BAD
int temp = x; // temp is a local variable
x = y; // changes only local copy
y = temp; // changes only local copy
}
Because x and y are value parameters, like local variables, changes to them have no effect on
the calling functions arguments a and b.
Example - Swap (good solution)
If the parameters are marked as reference parameters, the memory address
of each argument is passed to the function. The function uses this address
to both get and set the value. Here is swap
written correctly.
The only change is the addition of the & to the parameter declaration following the type.
void swap(int& x, int& y) {
int temp = x; // temp is a local variable
x = y; // changes the actual parameter in the calling pgm.
y = temp; // changes the actual parameter in the calling pgm.
}
L-values required for actual reference parameters
An l-value is something that you can assign to. This name
is short for left-value, referring to the kind of value that
must be on the left side of an assignment statement.
All actual reference parameters must have an l-value.
swap(1, 2); // BAD - literals don't have l-values.
swap(x+5, c); // BAD - numeric expressions don't have l-values.
swap(x, y); // OK - variables are l-values.
swap(a[i], a[i+1]); // OK - array references are l-values.
It's easy to figure this out if you just think about what you
can write on the left of an assignment; '1', '2', and 'x+5' are
obviously not legal.