题 我们可以在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

46
2018-02-15 12:47


起源




答案:


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

没有, ri 仍然是一个参考 i  - 你可以通过印刷来证明这一点 &ri 和 &i 并且看到他们是同一个地址。

你做的是修改 i  通过 参考资料 ri。打印 i 之后,你会看到这个。

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


51
2018-02-15 12:50



为什么是 const int &cri = i 不允许?在哪一行你不能写那个?因为我编译器允许在任何地方插入这样的行。除此之外,它是一个清晰简洁的答案! - mercury0114
我没有说这是不被允许的 - 正如你所观察到的,将const ref作为非const变量就可以了。我说了 不会让你分配给那个,意思是你不能通过const ref改变原始变量,就像OP一样 ri。 - Useless
哦,对了,我现在明白你的意思了。 - mercury0114
我每次都“犯” - Sameer Puri


好像我实际上成功地重新分配了一个引用。   真的吗?

没有,你没有。您实际上正在重新分配该值,并且您没有重新引用该引用。

在你的例子中,当你这样做 int &ri = i;ri 一定会 i 一生。当你这样做 ri = j;,你只是分配值 j 至 riri 仍然是一个参考 i!并且它会产生与您编写的相同的结果 i = j;

如果你理解指针很好,那么总是把参考文献看作是类比的解释 T* const 哪里 T 是任何类型。


7
2018-02-15 12:51





为引用赋值时,实际将值赋给引用绑定的对象。所以这:

ri=j;

具有相同的效果

i = j;

会因为 ri 一定会 i。所以任何行动 ri 被执行 i


3
2018-02-15 12:50





执行时,您不会重新分配引用 ri = j;。你实际上在分配 j 至 i。尝试打印 i 在线后,你会看到 i 改变了价值。


3
2018-02-15 12:50





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),引用在内存中保留了完全相同的地址,但引用的值(向量的一部分)已在其他地方重新分配。参考我可能是悬空。


0
2017-11-16 21:13