I know references are syntactic sugar, so code is easier to read and write.
But what are the differences?
Summary from answers and links below:
- A pointer can be re-assigned any number of times while a reference cannot be re-assigned after binding.
- Pointers can point nowhere (
NULL
), whereas a reference always refers to an object. - You can't take the address of a reference like you can with pointers.
- There's no "reference arithmetic" (but you can take the address of an object pointed by a reference and do pointer arithmetic on it as in
&obj + 5
).
To clarify a misconception:
The C++ standard is very careful to avoid dictating how a compiler may implement references, but every C++ compiler implements references as pointers. That is, a declaration such as:
int &ri = i;
if it's not optimized away entirely, allocates the same amount of storage as a pointer, and places the address of
i
into that storage.
So, a pointer and a reference both use the same amount of memory.
As a general rule,
- Use references in function parameters and return types to provide useful and self-documenting interfaces.
- Use pointers for implementing algorithms and data structures.
Interesting read:
- My all-time favorite C++ FAQ lite.
- References vs. Pointers.
- An Introduction to References.
- References and const.
Maybe some metaphors will help; In the context of your desktop screenspace -
A reference to a pointer is possible in C++, but the reverse is not possible means a pointer to a reference isn't possible. A reference to a pointer provides a cleaner syntax to modify the pointer. Look at this example:
And consider the C version of the above program. In C you have to use pointer to pointer (multiple indirection), and it leads to confusion and the program may look complicated.
Visit the following for more information about reference to pointer:
As I said, a pointer to a reference isn't possible. Try the following program:
If you want to be really pedantic, there is one thing you can do with a reference that you can't do with a pointer: extend the lifetime of a temporary object. In C++ if you bind a const reference to a temporary object, the lifetime of that object becomes the lifetime of the reference.
In this example s3_copy copies the temporary object that is a result of the concatenation. Whereas s3_reference in essence becomes the temporary object. It's really a reference to a temporary object that now has the same lifetime as the reference.
If you try this without the
const
it should fail to compile. You cannot bind a non-const reference to a temporary object, nor can you take its address for that matter.I feel like there is yet another point that hasn't been covered here.
Unlike the pointers, references are syntactically equivalent to the object they refer to, i.e. any operation that can be applied to an object works for a reference, and with the exact same syntax (the exception is of course the initialization).
While this may appear superficial, I believe this property is crucial for a number of C++ features, for example:
Templates. Since template parameters are duck-typed, syntactic properties of a type is all that matters, so often the same template can be used with both
T
andT&
.(or
std::reference_wrapper<T>
which still relies on an implicit cast toT&
)Templates that cover both
T&
andT&&
are even more common.Lvalues. Consider the statement
str[0] = 'X';
Without references it would only work for c-strings (char* str
). Returning the character by reference allows user-defined classes to have the same notation.Copy constructors. Syntactically it makes sense to pass objects to copy constructors, and not pointers to objects. But there is just no way for a copy constructor to take an object by value - it would result in a recursive call to the same copy constructor. This leaves references as the only option here.
Operator overloads. With references it is possible to introduce indirection to an operator call - say,
operator+(const T& a, const T& b)
while retaining the same infix notation. This also works for regular overloaded functions.These points empower a considerable part of C++ and the standard library so this is quite a major property of references.
I use references unless I need either of these:
Null pointers can be used as a sentinel value, often a cheap way to avoid function overloading or use of a bool.
You can do arithmetic on a pointer. For example,
p += offset;
Another difference is that you can have pointers to a void type (and it means pointer to anything) but references to void are forbidden.
I can't say I'm really happy with this particular difference. I would much prefer it would be allowed with the meaning reference to anything with an address and otherwise the same behavior for references. It would allow to define some equivalents of C library functions like memcpy using references.