When returning a value from a function, the default for C++ is to return a copy of the value. Program 1 shows this very explictly by returning the value of a static variable.
Program 1. Returning by value.
#include <iostream> using namespace std; int f() { static int n = 0; ++n; cout << "Returning the static value " << n << endl; return n; } int main() { int result = f(); ++result; cout << "The incremented result is " << result << endl; f(); return 0; } |
If you run this, you will note that the static value is only incremented inside the function int f().
If you want to return by reference, you must, like parameters, append an & to the return type. To actually use this, see Program 2.
Program 2. Returning by reference.
#include <iostream> using namespace std; int & f() { static int n = 0; ++n; cout << "Returning the static value " << n << endl; return n; } int main() { int result = f(); ++result; cout << "1. The incremented result is " << result << endl; result = ++f(); cout << "2a. The incremented result is " << result << endl; ++result; cout << "2b. The doubly-incremented result is " << result << endl; f(); int & rresult = f(); ++rresult; cout << "3. The incremented result is " << rresult << endl; f(); return 0; } |
To determine what is happening, note that the first assignment, int result = f();, assigns the returned reference to a variable. Thus, the assignment is done by copying the value.
In the second assigment, because int f() returns a reference, the reference in turn can be passed onto ++ which increments the referred-to variable, in this case, the static variable of int f(), however, once the value is assigned to result, once again, a copy is made and changes to result do not affect the static variable.
In the third case, we assign the result of the function to a variable which was declared to be a reference to an integer, and therefore, any modifications to the variable must affect the static variable inside int f().
There are cases where returning by reference is useful, and even necessary, however, you must be careful to to make sure you know what you're doing. Two examples which do return by reference are overloading the << operator when the first argument is of type ostream (for example, cout) and the second argument is of your specific type. Program 3 demonstrates how << can be overloaded, however, to ensure that it continues to work, it must return
Program 3. Returning by reference.
#include <iostream> using namespace std; ostream & operator << ( ostream & os, double array[10] ) { os << " a pointer to a double: "; for ( int i = 0; i < 9; ++i ) { os << array[i] << "-"; } os << array[9] << endl; return os; } int main() { double x[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; cout << x; return 0; } |
Another reason for returning by reference is to gain the default behaviour of the ++ operator, however,
If you are returning a reference to an object, make sure that the object exists. Specifically, do not return a reference if the object being returned is a local variable to the function. When the function exits, the memory allocated (on the stack) for the local variable is deallocated.