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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9293674/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 12:36:53  来源:igfitidea点击:

Can we reassign the reference in C++?

c++reference

提问by Invictus

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

回答by Useless

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

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

No, riis still a reference to i- you can prove this by printing &riand &iand seeing they're the same address.

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

What you did is modify ithroughthe reference ri. Print iafter, and you'll see this.

您所做的是i通过参考进行修改rii之后打印,你会看到这个。

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

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

回答by iammilind

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;, riis bound to ifor its lifetime. When you do ri = j;, you are simply assigning the value of jto ri. ristill remains a reference to i! And it results in the same outcome as if you had instead written i = j;

在您的示例中,当您这样做时int &ri = i;, ,ri必然会i持续其一生。当您这样做时ri = j;,您只是将值分配给jto riri仍然是一个参考i!它的结果与你写的结果相同i = j;

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

如果您很好地理解指针,那么请始终将引用视为T* constwhere Tis any 类型的类比解释。

回答by sharptooth

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 riis bound to i. So any action on riis executed on i.

会有因为ri是必然的i。所以任何 on 的动作ri都是在上执行的i

回答by Eric Fortin

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

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

回答by Jan

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.

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;

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.

结论:至少在我的情况下(VS2017),引用在内存中保留了完全相同的地址,但引用的值(向量的一部分)已在其他地方重新分配。参考我可能悬而未决。

回答by Sid

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

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

One useful mantra with references in C++ is that the references arethe object they refer to. Any change you make to it isto 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 isj.

在C ++的引用的一个有用的咒语的是,参考文献它们引用的对象。您对其所做的任何更改都是对其所指的内容进行更改。使用咒语,您可能会看到当您这样做时发生了什么ri = j,我现在j。