An alias (an alternate name) for an object.
References are frequently used for pass-by-reference:
Here i and j are aliases for main's x and y respectively. In other words, i is x not a pointer to x, nor a copy of x, but x itself. Anything you do to i gets done to x, and vice versa.
OK. That's how you should think of references as a programmer. Now, at the
risk of confusing you by giving you a different perspective, here's how
references are implemented. Underneath it all, a reference i to object x
is typically the machine address of the object x. But when the programmer
says
Important note: Even though a reference is often implemented using an address in the underlying assembly language, please do not think of a reference as a funny looking pointer to an object. A reference is the object. It is not a pointer to the object, nor a copy of the object. It is the object.
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
You change the state of the referent (the referent is the object to which the reference refers).
Remember: the reference is the referent, so changing the reference changes the state of the referent. In compiler writer lingo, a reference is an "lvalue" (something that can appear on the left hand side of an assignment operator).
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
The function call can appear on the left hand side of an assignment operator.
This ability may seem strange at first. For example, no one thinks the
expression
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
It chains these method calls, which is why this is called method chaining.
The first thing that gets executed is
The most common use of method chaining is in the iostream library.
E.g.,
A less common, but still rather slick, use for method chaining is in the Named Parameter Idiom.
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
No way.
You can't separate the reference from the referent.
Unlike a pointer, once a reference is bound to an object, it can not be "reseated" to another object. The reference itself isn't an object (it has no identity; taking the address of a reference gives you the address of the referent; remember: the reference is its referent).
In that sense, a reference is similar to a const
pointer such as
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
Use references when you can, and pointers when you have to.
References are usually preferred over pointers whenever you don't need "reseating". This usually means that references are most useful in a class's public interface. References typically appear on the skin of an object, and pointers on the inside.
The exception to the above is where a function's parameter or return value needs a "sentinel" reference a reference that does not refer to an object. This is usually best done by returning/taking a pointer, and giving the NULL pointer this special significance (references should always alias objects, not a dereferenced NULL pointer).
Note: Old line C programmers sometimes don't like references since they provide reference semantics that isn't explicit in the caller's code. After some C++ experience, however, one quickly realizes this is a form of information hiding, which is an asset rather than a liability. E.g., programmers should write code in the language of the problem rather than the language of the machine.
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
The term handle is used to mean any technique that lets you get to another object a generalized pseudo-pointer. The term is (intentionally) ambiguous and vague.
Ambiguity is actually an asset in certain cases. For example, during early design you might not be ready to commit to a specific representation for the handles. You might not be sure whether you'll want simple pointers vs. references vs. pointers-to-pointers vs. references-to-pointers vs. integer indices into an array vs. strings (or other key) that can be looked up in a hash-table (or other data structure) vs. database keys vs. some other technique. If you merely know that you'll need some sort of thingy that will uniquely identify and get to an object, you call the thingy a Handle.
So if your ultimate goal is to enable a glop of code to uniquely
identify/look-up a specific object of some class Fred, you need to
pass a Fred handle into that glop of code. The handle might be a
string that can be used as a key in some well-known lookup table (e.g., a key
in a
Novices often think in terms of pointers, but in reality there are downside
risks to using raw pointers. E.g., what if the Fred object needs to
move? How do we know when it's safe to delete the Fred
objects? What if the Fred object needs to (temporarily) get
serialized on disk? etc., etc. Most of the time we add more layers of
indirection to manage situations like these. For example, the handles might
be
The point is that we use the word Handle when we don't yet know the details of what we're going to do.
Another time we use the word Handle is when we want to be vague about what we've already done (sometimes the term magic cookie is used for this as well, as in, "The software passes around a magic cookie that is used to uniquely identify and locate the appropriate Fred object"). The reason we (sometimes) want to be vague about what we've already done is to minimize the ripple effect if/when the specific details/representation of the handle change. E.g., if/when someone changes the handle from a string that is used in a lookup table to an integer that is looked up in an array, we don't want to go and update a zillion lines of code.
To further ease maintenance if/when the details/representation of a handle
changes (or to generally make the code easier to read/write), we often
encapsulate the handle in a class. This class often
overloads operators
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
E-mail the author
[ C++ FAQ Lite
| Table of contents
| Subject index
| About the author
| ©
| Download your own copy ]
Revised Mar 1, 2006