我到处都读过必须初始化引用然后再进行重新初始化。
为了测试我的理解,我写了以下小程序。似乎我已经成功地重新分配了一个引用。有人可以向我解释一下我的程序实际发生了什么吗?
#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
答案 0 :(得分:64)
ri = j; // >>> Is this not reassigning the reference? <<<
不,ri
仍然是对i
的引用 - 您可以通过打印&ri
和&i
并看到它们是相同的地址来证明这一点。
您所做的是通过引用i
修改ri
。之后打印i
,您就会看到这一点。
此外,为了进行比较,如果您创建const int &cri = i;
,则不会让您分配给它。
答案 1 :(得分:9)
好像我确实成功地重新分配了一个引用。 这是真的吗?
没有,你没有。您实际上正在重新分配该值,并且您没有重新引用该引用。
在您的示例中,当您执行int &ri = i;
时,ri
在其生命周期内绑定到i
。执行ri = j;
后,您只需将j
的值分配给ri
。 ri
仍然是i
的引用!并且它会产生与您编写i = j;
如果您理解指针,那么请始终将该引用视为T* const
的类比解释,其中T
为任何类型。
答案 2 :(得分:4)
当您为引用分配内容时,实际上将值赋给引用所绑定的对象。所以这个:
ri=j;
与
具有相同的效果i = j;
会因为ri
绑定到i
。因此ri
上的所有操作都会在i
上执行。
答案 3 :(得分:3)
执行ri = j;
时,您不会重新分配参考。您实际上是将j
分配给i
。尝试在该行后打印i
,您会看到i
更改了值。
答案 4 :(得分:1)
OP要求通过赋值给引用来改变引用的对象,并且非常正确地告知这改变了引用对象,而不是引用。 现在我做了一个更痛苦的尝试,真正改变参考,并发现潜在的讨厌的东西。 首先是代码。它试图重新分配给引用var一个新创建的对象,然后改变引用的引用对象,发现这没有反映在明显引用的对象中,并得出结论我们可能在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),引用在内存中保留了完全相同的地址,但引用的值(向量的一部分)已在其他地方重新分配。参考我可能正在晃来晃去。
答案 5 :(得分:0)
您不能“重置”参考文献(https://isocpp.org/wiki/faq/references#reseating-refs)。
在C ++中使用引用的一个有用的口头禅是,引用是他们所引用的对象。您对所做的任何更改都是对他们所指的内容进行更改。使用咒语,您可能可以看到ri = j
做的事,我现在是 j。