我们可以在 C + + 中重新分配引用吗?

我到处都读到过引用必须当时当地初始化,而且不能再重新初始化。

为了测试我的理解力,我编写了以下小程序。似乎我已经成功地重新分配了一个引用。谁能给我解释一下我的程序里到底发生了什么?

#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;
}

代码编译得很好,输出正如我所期望的那样:

ri is : 5
ri is : 10
ri is : 9
43233 次浏览

当您为引用赋值时,您实际上是为引用绑定到的对象赋值。所以这个:

ri=j;

和... 有同样的效果

i = j;

因为 ri绑定到 i,所以对 ri的任何操作都是在 i上执行的。

执行 ri = j;时不会重新分配引用。你实际上是把 j分配给 i。试着在这行后面打印 i,你会看到 i改变了值。

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

不,ri仍然是对 i的引用-你可以通过打印 &ri&i来证明它们是同一个地址。

你所做的是修改 i 通过参考 ri。打印 i后,你会看到这一点。

另外,为了比较,如果您创建一个 const int &cri = i;,它不会让您分配给它。

似乎我已经成功地重新分配了一个引用。 是真的吗?

,您没有。您实际上是在重新分配值,而不是重新绑定引用。

在您的示例中,当执行 int &ri = i;时,ri将在其生存期内绑定到 i。执行 ri = j;时,只需将 j的值赋给 riri仍然是对 i的引用!它的结果与编写 i = j;的结果相同

如果您很好地理解了指针,那么总是认为参考作为 T* const的类比解释,其中 T是任何类型。

OP 要求通过对引用的赋值来更改引用对象,并被正确地告知这更改了引用对象,而不是引用。 现在我做了一个更辛辣的尝试,真正改变参考和发现潜在的讨厌的东西。 首先是密码。它尝试将一个新创建的对象重新赋值给引用 var,然后改变引用 aka 引用对象,发现这没有反映在明显被引用的对象中,最后得出结论,我们可能在 C + + 中遇到了一个迷途指针。对于匆忙编写的代码,我表示抱歉。

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;

产出:

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

结论: 至少在我的案例中(VS2017) ,引用在内存中保持了完全相同的地址,但是引用的值(部分向量)被重新分配到了其他地方。参考文献,我可能悬而未决。

您不能“重置”一个参考(https://isocpp.org/wiki/faq/references#reseating-refs)。

对于 C + + 中的引用,一个有用的箴言是,引用 就是它们所引用的对象。您对它进行的任何更改 都是为了对它们所引用的内容进行更改。使用咒语,你可能会看到发生了什么,当你做 ri = j,我现在 j。

简而言之,

ri = j; <-在 x (ri)内存中写入 j 的值。