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 11.2 demonstrates this.
1: // Demonstrating the use of References 2: #include <iostream> 3: 4: int main() 5: { 6: int intOne; 7: int &rSomeRef = intOne; 8: 9: intOne = 5; 10: std::cout << "intOne: " << intOne << std::endl; 11: std::cout << "rSomeRef: " << rSomeRef << std::endl; 12: 13: std::cout << "&intOne: " << &intOne << std::endl; 14: std::cout << "&rSomeRef: " << &rSomeRef << std::endl; 15: 16: return 0; 17: } |
For example, if you had a class called President, you might declare an instance of that class as follows:
President George_W._Bush;
You might then declare a reference to President and initialize it with this object:
President &Dubya = George_W._Bush;
There is only one President; both identifiers refer to the same object of the same class. Any action you take on Dubya will be taken on George_W._Bush as well.
Be careful to distinguish between the & symbol on line 7 of Listing 11.2, which declares a reference to int named rSomeRef, and the & symbols on lines 13 and 14, 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 11.
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 11.3 illustrates this fact.
0: //Listing 11.3 1: //Reassigning a reference 2: #include <iostream> 3: using namespace std; // use std:: objects in this file 4: 5: int main() 6: { 7: int intOne; 8: int &rSomeRef = intOne; 9: 10: intOne = 5; 11: cout << "intOne: " << intOne << endl; 12: cout << "rSomeRef: " << rSomeRef << endl; 13: cout << "&intOne: " << &intOne << endl; 14: cout << "&rSomeRef: " << &rSomeRef << endl; 15: 16: int intTwo = 8; 17: rSomeRef = intTwo; // not what you think! 18: cout << " intOne: " << intOne << endl; 19: cout << "intTwo: " << intTwo << endl; 20: cout << "rSomeRef: " << rSomeRef << endl; 21: cout << "&intOne: " << &intOne << endl; 22: cout << "&intTwo: " << &intTwo << endl; 23: cout << "&rSomeRef: " << &rSomeRef << endl; 24: return 0; 25: } |
intOne: 5 rSomeRef: 5 &intOne: 0x0012FF7C &rSomeRef: 0x0012FF7C intOne: 8 intTwo: 8 rSomeRef: 8 &intOne: 0x0012FF7C &intTwo: 0x0012FF74 &rSomeRef: 0x0012FF7C
On line 16 a new variable, intTwo, is created and initialized with the value 8. On line 17 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 18–20) they are the same as intTwo. In fact, when the addresses are printed on lines 21–23, you see that rSomeRef continues to refer to intOne and not intTwo.
|
18.188.152.136