Chapter 11. References

FAQ 11.01 What is a reference?

A reference is an alias, an alternate name for an object. References are frequently used for passing parameters by reference (pass-by-reference; see FAQ 2.09). In the following example, function swap() receives its parameters by non-const reference since it needs to change the values of the caller's actual parameters, in this case main()'s i and j.

image

Here x and y become aliases for main()'s i and j, respectively. The effect is similar to the C-style pass-by-pointer, but without the caller having to take the address of the parameters and without the callee having to dereference pointers. That is, it would be illegal to change swap(i, j) in main() to swap(&i, &j), and it would be illegal to change x = y in swap() to *x = *y.

FAQ 11.02 What does “referent” mean?

“Referent” is a synonym for the object to which the reference refers; see FAQ 2.09. In the following example, j is the reference and i is the referent.

image

FAQ 11.03 When can a reference be attached to its referent?

A reference can be attached to its referent only at the moment the reference is initialized. Not only that, C++ requires every reference initialization to have a referent.

The following example initializes j to be an alias for i, but the initialization of k is illegal because reference k is not attached to an object.

image

When a function receives a parameter by reference, the reference is initialized by being attached (bound) to the actual argument provided by the caller.

FAQ 11.04 What happens when a value is assigned to a reference?

The reference remains bound to the same referent, and the value of the referent is changed.

Because a reference is an alias for its referent, anything done to the reference is actually done to the referent. In particular, a reference is an lvalue (an expression that can appear on the left side of an assignment operator) for the referent. Therefore, assigning to a reference changes the referent.

Said another way, a reference is its referent—not a copy of the referent nor a pointer to the referent, but the referent itself.

For example, in the following function f(), the first statement changes main()'s i because the formal parameter x is an alias for i. The second statement also changes i (as well as x) because the address of i is stored in y. The third statement does not change i because z is a copy of the original value of i.

image

FAQ 11.05 What is a local reference?

A local reference is a local (auto) reference variable that isn't a parameter. The following example illustrates how local references provide a temporary alias relationship. Integer reference j is an alias for integer i, so changing i to 5 changes j, and changing j changes i.

image

FAQ 11.06 What does it mean to return a reference?

The function call expression is an lvalue to the referent.

When a function returns a reference, the function call becomes an lvalue (see FAQ 11.04) for the referent. This is normally used to allow operator expressions (such as the subscript operator, the dereference operator, and so on) to be used as lvalues. The following example shows how returning a reference allows a subscript operator to be an lvalue.

image

Returning a reference to data_[i] doesn't return a copy of data_[i]; it returns data_[i] itself. Therefore, anything done to the expression in the caller (a[i]) is actually done to data_[i]. In the example, the statement a[i] =...actually changes data_[i] within object a.

C programmers should note that this allows a function call to appear on the left side of an assignment operator.

FAQ 11.07 What is the result of taking the address of a reference?

The address of a reference is the address of the referent.

Remember that the reference is the referent. Anything done to the reference—including taking its address—is actually done to the referent. For example, the following code will print yes since &i will be equal to &j.

image

FAQ 11.08 Can a reference be made to refer to a different referent?

No, it can't.

Unlike a pointer, once a reference is bound to an object, it cannot be made to refer to a different object. The alias cannot be separated from the referent.

For example, the last line of the following example changes i to 6; it does not make the reference k refer to j. Throughout its short life, k will always refer to i.

image

FAQ 11.09 Why use references when pointers can do everything references can do?

Because references are better than pointers for some tasks.

Using a pointer when a reference will do is like using a chain saw to trim your fingernails—it will do the job, but you'd better be extremely careful.

In C, pointers are used for a variety of tasks because there is no other tool available for doing these tasks. Programmers learn to live with the dangers of pointers in C because there is no alternative. It's as if C gives you a chain saw and expects you to use it for building houses, shredding paper, trimming fingernails, and cutting hair.

When all that's needed is an alias for an object, a pointer is overkill, but a reference is ideal. Pointers are a powerful and valuable part of any programmer's toolbox. However, they should be used only when necessary. Don't give a chain saw to a user who just wants a manicure.

Use references when you can, use pointers when you have to. (See FAQ 11.11.)

FAQ 11.10 Aren't references just pointers in disguise?

No, they are not.

It is important to realize that references and pointers are quite different. A pointer should be thought of as a separate object with its own distinct set of operations (*p, p->blah, and so on). So creating a pointer creates a new object. In contrast, creating a reference does not create a new object; it merely creates an alternative name for an existing object. Furthermore the operations and semantics for the reference are defined by the referent; references do not have operations of their own.

In the following example, notice that assigning 0 to the reference j is very different than assigning 0 to the pointer p (the 0 pointer is the same as the NULL pointer; see FAQ 1.09).

image

Because of their low-level nature, pointers are poor substitutes for references. Holding on to the belief that pointers and references are the same is like saying that char* and a string class are the same or that void* and long are the same—there is a way to map from one to the other but the mapping is forced and is unnatural. Furthermore, the purpose of programming in C++ is not to write C++ programs that look just like C programs.

Pointers and references are not the same, even though many compilers implement them using similar assembly language instructions. This is an implementation detail that does not change the message of this FAQ.

FAQ 11.11 When are pointers needed?

References are usually preferred over pointers when aliases are needed for existing objects, making them useful in parameter lists and as return values. Pointers are required when it might be necessary to change the binding to a different referent or to refer to a nonobject (a NULL pointer). Pointers often show up as local variables and member objects. An example of this can be seen in the class Array that follows.

image

The only time a parameter or return value should be a pointer is when the function needs to accept or return a sentinel value. In this case the function can accept or return a pointer and use the NULL pointer as the sentinel value.

FAQ 11.12 Why do some people hate references?

Most of the complaints we've heard about references have come from C programmers who are new to C++, and the complaints reflect a combination of teaching old dogs new tricks and the lack of good training on what references are all about.

It often takes C programmers time to get used to references. In the beginning, C programmers typically complain that pass-by-reference doesn't require explicit syntax in the caller's source code (for example, no & in the caller code). After using C++ for a while, however, developers realize that this is information hiding, which is an asset rather than a liability.

An important goal of OO technology is to enable developers to program in the language of the problem domain rather than the language of the computer. The information hiding provided by a reference is a small step in the migration.

In C, the maxim is “No hidden mechanism.” C++ intentionally discards this C maxim since it is inconsistent with the C++ goal of programming in the language of the problem domain rather than the language of the machine. The new maxim is “Pay for it only if you use it.”

Write C++ code in the language of the problem domain, not the language of the machine.

FAQ 11.13 Does int& const x make sense?

No, it doesn't. Since a reference is always bound to the same referent, the const is superfluous and possibly confusing.

image

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset