我们可以在C ++中重新分配参考吗?


72

我到处都读到必须先初始化引用,然后再重新初始化。

为了测试我的理解,我编写了以下小程序。似乎我实际上已经成功地重新分配了参考。有人可以向我解释程序中实际发生了什么吗?

#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

Answers:


82

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

没有,ri仍然是一个参考i-您可以通过打印证明这一点&ri&i,看到他们是同一个地址。

您所做的是i 通过参考进行修改rii之后打印,您将看到此信息。

另外,为了进行比较,如果创建一个const int &cri = i;,则不允许您分配给它。


为什么const int &cri = i不允许?在哪一行你不能写?对我而言,编译器允许在任何位置插入此类行。除此之外,这是一个清晰简洁的答案!
水银0114年

我没有说这是不允许的-正如您所观察到的,将const ref引用到非const变量就可以了。我说过,它不会让您分配给它,这意味着您不能像OP那样通过const ref更改原始变量ri
没用的

7
我每次都“犯罪”
Sameer Puri

14

似乎我实际上已经成功地重新分配了参考。真的吗?

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

在您的示例中,当您执行时int &ri = i;ri必然会i终身存在。这样做时ri = j;,您只需分配jto的值riri仍然是一个参考i!结果与您撰写的结果相同i = j;

如果您很好地理解了指针,则始终将引用视为对T* const哪里T是任何类型的类比解释。


5

当您为引用分配某些内容时,实际上是将值分配给引用所绑定的对象。所以这:

ri=j;

与...具有相同的效果

i = j;

会因为ri势必绑定i。因此,对的所有操作都会在ri上执行i


3

执行时您没有重新分配引用ri = j;。您实际上是在分配ji。尝试i在行之后打印,您将看到i更改后的值。


2

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

您不能“重置”引用(https://isocpp.org/wiki/faq/references#reseating-refs)。

C ++中引用的一个有用的口头禅是,引用它们所引用的对象。您对其所做的任何更改都是对他们所指的内容进行更改。使用该咒语,您可能可以看到您正在做的事情ri = j,我现在j。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.