|

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.
|