A reference serves one purpose: to act as an alias for an existing variable:
int i;
int &ri = i;
In this example, the addresses of i
and ri
are identical (&i == &ri
). The two names refer to the very same location in memory. Thus one of the useful applications of references is to provide an alias for a long name that it would be wasteful to retype:
const Location& p = irresponsibly_long_object_name.retrieve_location();
When you pass a function parameter by reference, it has the same effect:
void increment(int& parameter) { ++parameter; }
int main(int argc, char** argv) {
int variable = 0;
increment(variable);
}
Here, parameter
serves merely as an alias of variable
, just as though it were defined as int& parameter = variable
. Modifying parameter
inside increment()
is indistinguishable from modifying variable
in main()
. Furthermore—and this is quite useful—variable
does not need to be copied; so if it were of a large type such as std::list<int>
, then passing it by reference would be much more efficient. That’s the main point of const
references.
For the purpose of function parameters of reference type, the sanest course of action for a compiler is to use a pointer internally, as if you had written:
void increment(int* parameter) { ++*parameter; }
int main(int argc, char** argv) {
int variable = 0;
increment(&variable);
}
This is an interesting detail, and well worthwhile to remember. While it is not essential to your understanding of references, recognising this equivalence allows you to think of pointers merely as explicit references. Likewise, references are implicit pointers.