C++

What Is a  Reference ?

A reference is an alias; when you create a reference, you initialize it with the name of another object, the target. From that moment on, the reference acts as an alternative name for the target, and anything you do to the reference is really done to the target.

You create a reference by writing the type of the target object, followed by the reference operator (&), followed by the name of the reference. References can use any legal variable name, but for this book we’ll prefix all reference names with "r." Thus, if you have an integer variable named someInt, you can make a reference to that variable by writing the following:

int &rSomeRef = someInt;

This is read as "rSomeRef is a reference to an integer that is initialized to refer to someInt." Listing 9.1 shows how references are created and used.

NOTE: Note that the reference operator (&) is the same symbol as the one used for the address of the operator. These are not the same operators, however, though clearly they are related.

Listing 9.1. Creating and using references.

1: //Listing 9.1

2: // Demonstrating the use of References

3:

4: #include <iostream.h>

5:

6: int main()

7: {

8: int intOne;

9: int &rSomeRef = intOne;

10:

11: intOne = 5;

12: cout << "intOne: " << intOne << endl;

13: cout << "rSomeRef: " << rSomeRef << endl;

14:

15: rSomeRef = 7;

16: cout << "intOne: " << intOne << endl;

17: cout << "rSomeRef: " << rSomeRef << endl;

18: return 0;

19: }

OUTPUT: 

intOne: 5

rSomeRef: 5

intOne: 7

rSomeRef: 7

ANALYSIS: On line 8, a local int variable, intOne, is declared. On line 9, a reference to an int, rSomeRef, is declared and initialized to refer to intOne. If you declare a reference, but don’t initialize it, you will get a compile-time error. References must be initialized.
On line 11, intOne is assigned the value 5. On lines 12 and 13, the values in intOne and rSomeRef are printed, and are, of course, the same.

On line 15, 7 is assigned to rSomeRef. Since this is a reference, it is an alias for intOne, and thus the 7 is really assigned to intOne, as is shown by the printouts on lines 16 and 17.

Using the Address of Operator & on References

If you ask a reference for its address, it returns the address of its target. That is the nature of references. They are aliases for the target. Listing 9.2 demonstrates this.

Listing 9.2. Taking the address of a reference.

1: //Listing 9.2

2: // Demonstrating the use of References

3:

4: #include <iostream.h>

5:

6: int main()

7: {

8: int intOne;

9: int &rSomeRef = intOne;

10:

11: intOne = 5;

12: cout << "intOne: " << intOne << endl;

13: cout << "rSomeRef: " << rSomeRef << endl;

14:

15: cout << "&intOne: " << &intOne << endl;

16: cout << "&rSomeRef: " << &rSomeRef << endl;

17:

18: return 0;

19: }

OUTPUT: 

intOne: 5

rSomeRef: 5

&intOne: 0x3500

&rSomeRef: 0x3500

NOTE: Your output may differ on the last two lines.

ANALYSIS: Once again rSomeRef is initialized as a reference to intOne. This time the addresses of the two variables are printed, and they are identical. C++ gives you no way to access the address of the reference itself because it is not meaningful, as it would be if you were using a pointer or other variable. References are initialized when created, and always act as a synonym for their target, even when the address of operator is applied. For example, if you have a class called President, you might declare an instance of that class as follows:

President William_Jefferson_Clinton;

You might then declare a reference to President and initialize it with this object:

President &Bill_Clinton = William_Jefferson_Clinton;

There is only one President; both identifiers refer to the same object of the same class. Any action you take on Bill_Clinton will be taken on William_Jefferson_Clinton as well.

Be careful to distinguish between the & symbol on line 9 of Listing 9.2, which declares a reference to int named rSomeRef, and the & symbols on lines 15 and 16, which return the addresses of the integer variable intOne and the reference rSomeRef.

Normally, when you use a reference, you do not use the address of operator. You simply use the reference as you would use the target variable. This is shown on line 13.

Even experienced C++ programmers, who know the rule that references cannot be reassigned and are always aliases for their target, can be confused by what happens when you try to reassign a reference. What appears to be a reassignment turns out to be the assignment of a new value to the target. Listing 9.3 illustrates this fact.

Listing 9.3. Assigning to a reference.

1: //Listing 9.3

2: //Reassigning a reference

3:

4: #include <iostream.h>

5:

6: int main()

7: {

8: int intOne;

9: int &rSomeRef = intOne;

10:

11: intOne = 5;

12: cout << "intOne:\t" << intOne << endl;

13: cout << "rSomeRef:\t" << rSomeRef << endl;

14: cout << "&intOne:\t" << &intOne << endl;

15: cout << "&rSomeRef:\t" << &rSomeRef << endl;

16:

17: int intTwo = 8;

18: rSomeRef = intTwo; // not what you think!

19: cout << "\nintOne:\t" << intOne << endl;

20: cout << "intTwo:\t" << intTwo << endl;

21: cout << "rSomeRef:\t" << rSomeRef << endl;

22: cout << "&intOne:\t" << &intOne << endl;

23: cout << "&intTwo:\t" << &intTwo << endl;

24: cout << "&rSomeRef:\t" << &rSomeRef << endl;

25: return 0;

26: }

OUTPUT:

 intOne: 5

rSomeRef: 5

&intOne: 0x213e

&rSomeRef: 0x213e

intOne: 8

intTwo: 8

rSomeRef: 8

&intOne: 0x213e

&intTwo: 0x2130

&rSomeRef: 0x213e

ANALYSIS: Once again, an integer variable and a reference to an integer are declared, on lines 8 and 9. The integer is assigned the value 5 on line 11, and the values and their addresses are printed on lines 12-15. On line 17, a new variable, intTwo, is created and initialized with the value 8. On line 18, the programmer tries to reassign rSomeRef to now be an alias to the variable intTwo, but that is not what happens. What actually happens is that rSomeRef continues to act as an alias for intOne, so this assignment is exactly equivalent to the following:

intOne = intTwo;

Sure enough, when the values of intOne and rSomeRef are printed (lines 19-21) they are the same as intTwo. In fact, when the addresses are printed on lines 22-24, you see that rSomeRef continues to refer to intOne and not intTwo.

DO use references to create an alias to an object. DO initialize all references. DON’T try to reassign a reference. DON’T confuse the address of operator with the reference operator.

Back to Index