Can we reassign the reference in C++?

C++Reference

C++ Problem Overview


I have read everywhere that a reference has to be initialized then and there and can't be re-initialized again.

To test my understanding, I have written the following small program. It seems as if I have actually succeeded in reassigning a reference. Can someone explain to me what is actually going on in my program?

#include <iostream>
#include <stdio.h>
#include <conio.h>

using namespace std;

int main()
{
    int i = 5, j = 9;

    int &ri = i;
    cout << " ri is : " << ri  <<"\n";

    i = 10;
    cout << " ri is : " << ri  << "\n";

    ri = j; // >>> Is this not reassigning the reference? <<<
    cout << " ri is : " << ri  <<"\n";

    getch();
    return 0;
}

The code compiles fine and the output is as I expect:

ri is : 5
ri is : 10
ri is : 9

C++ Solutions


Solution 1 - C++

> ri = j; // >>> Is this not reassigning the reference? <<<

No, ri is still a reference to i - you can prove this by printing &ri and &i and seeing they're the same address.

What you did is modify i through the reference ri. Print i after, and you'll see this.

Also, for comparison, if you create a const int &cri = i; it won't let you assign to that.

Solution 2 - C++

> It seems as if I have actually succeeded in reassigning a reference. > Is that true?

No, you haven't. You are actually reassigning the value, and you are not rebinding the reference.

In your example, when you do int &ri = i;, ri is bound to i for its lifetime. When you do ri = j;, you are simply assigning the value of j to ri. ri still remains a reference to i! And it results in the same outcome as if you had instead written i = j;

If you understand pointers well, then always think of the reference as an analogical interpretation of T* const where T is any type.

Solution 3 - C++

When you assign something to a reference you actually assign the value to the object the reference is bound to. So this:

ri=j;

has the same effect as

i = j;

would have because ri is bound to i. So any action on ri is executed on i.

Solution 4 - C++

You are not reassigning the reference when executing ri = j;. You're actually assigning j to i. Try printing i after the line and you'll see that i changed value.

Solution 5 - C++

You cannot "reseat" a reference(https://isocpp.org/wiki/faq/references#reseating-refs).

One useful mantra with references in C++ is that the references are the object they refer to. Any change you make to it is to make change to what ever they refer to. Using the mantra you can probably see what's happening when you do ri = j, i now is j.

Solution 6 - C++

OP asked for altering the referenced object through assignment to the reference and was very correctly told that this changed the reference object, not the reference. Now I did a more poignant attempt at really changing the reference and found potentially nasty stuff. First the code. It attempts to reassign to the reference var a newly created object, then alters the reference aka referenced object, finds that this is not reflected in the apparently referenced objects and concludes that we may have a case of a dangling pointer in C++. Sorry for the hastily composed code.

using namespace std;
vector<int>myints;

auto &i = myints.emplace_back();   // allocate and reference new int in vector
auto myintsaddr = &myints; auto myintfrontaddr = &myints.front(); // for future reference
i = 1;                             // assign a value to the new int through reference
cout << hex << "address of i: 0x" << &i << " equals " << "address of 
myints.back(): 0x" << &myints.back() << '.' << endl;  // check reference as expected
i = myints.emplace_back();     // allocate new int in vector and assign to old reference variable
i = 2;                         // give another value to i
cout << "i=" << i << ", myints={" << myints[0] << ", "<< myints[1] << '}' << endl; // any change to potentially referenced objects?
cout << hex << "&i: 0x" << &i << " unequal to " << "&myints.back(): 0x" << &myints.back() << " as well as &myints.front(): 0x" << &myints.front() << endl;
cout << "Myints " << (myintsaddr== &myints?"not ":"") << "relocated from " << myintsaddr << " to " << &myints << endl;
cout << "Myints front() " << (myintfrontaddr == &myints.front() ? "not " : "") << "relocated from " << myintfrontaddr << " to " << &myints.front() << endl;

Output:

address of i: 0x0063C1A0 equals address of myints.back(): 0x0063C1A0.
i=2, myints={1, 0}
&i: 0x0063C1A0 unequal to &myints.back(): 0x0063F00C as well as &myints.front(): 0x0063F008
Myints not relocated from 0039FE48 to 0039FE48
Myints front() relocated from 0063C1A0 to 0063F008

Conclusion: at least in my case (VS2017) the reference has kept the exact same address in memory, but the referenced values (part of the vector) have been reallocated elsewhere. Reference i may be dangling.

Solution 7 - C++

In simple words,

ri = j; <- You are writing value of j in x(ri) memory. And ri will still hold or point to x.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionInvictusView Question on Stackoverflow
Solution 1 - C++UselessView Answer on Stackoverflow
Solution 2 - C++iammilindView Answer on Stackoverflow
Solution 3 - C++sharptoothView Answer on Stackoverflow
Solution 4 - C++Eric FortinView Answer on Stackoverflow
Solution 5 - C++SidView Answer on Stackoverflow
Solution 6 - C++JanView Answer on Stackoverflow
Solution 7 - C++Shankar SathishView Answer on Stackoverflow