The most frequent use of references is to avoid an expensive deep copy;
by default, C++ has value semantics, and if you write something like:
void f( std::vector<double> d );
The entire vector will be copied each time you invoke f
. So you write
something like:
void f( std::vector<double> const& d );
One place where this is particularly important is when defining a copy constructor. If you were to write:
MyType( MyType other );
, you would end up with infinite recursion since the compiler would
have to call the copy constructor in order to copy the argument to this constructor. (In fact, the compiler will only accept a constructor
which takes a reference to the copy constructor, precisely to avoid this
problem.)
Outside of constructors, this is really an optimization and could be
considered as premature optimization. In practice, however, the almost
universal convention is to pass class types by reference to const,
rather than by value.
References may also be used as out parameters; compared to a pointer,
they have the advantage that they cannot be null.
References can also be used to provide a "window" into the class data.
The classical example is the overload of operator[]
in std::vector
;
it returns a reference so that you can modify, take the address of, etc.
the actual element in the array.
Other than as parameters and return values, in the above cases,
references are somewhat rare. If you use one as a class member, for
example, you must be aware that you cannot give the class classical
assignment semantics. (This is not an issue if the class doesn't
support assignment.) As a global variable, they might be used to hide
the implementation of what is being referred to, but this is exceedingly
rare. As a local variable, about the only use I know, is to cache the
results of another expression which returns a reference: for example, if
I'm accessing someMap[aKey]
a large number of times in a short block
of code, it makes sense to write:
ValueType& element = someMap[aKey];
at the start, and use element
after that. (Note that this only makes
sense because someMap[aKey]
returns a reference.)