【问题标题】:Can we reassign the reference in C++?我们可以在 C++ 中重新分配引用吗?
【发布时间】:2012-02-15 12:47:27
【问题描述】:

我到处读到,引用必须在那时和那里被初始化,并且不能再次重新初始化。

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

#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

【问题讨论】:

  • 我确信最终 c++ 将添加引用重新分配作为一项功能。现在,使用指针。
  • C++ 在 C++11 中添加了std::reference_wrapper

标签: c++ reference


【解决方案1】:

ri = j; // &gt;&gt;&gt; Is this not reassigning the reference? &lt;&lt;&lt;

不,ri 仍然是对 i 的引用 - 您可以通过打印 &amp;ri&amp;i 并看到它们是同一个地址来证明这一点。

您所做的是修改i 通过引用ri。之后打印i,你会看到这个。

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

【讨论】:

  • 为什么不允许const int &amp;cri = i?在哪一行你不能写?因为对我来说,编译器允许在任何地方插入这样的行。除此之外,这是一个清晰简洁的答案!
  • 我并没有说这是不允许的 - 正如您所观察到的,将 const ref 用于非常量变量是可以的。我说过它不会让你分配给它,这意味着你不能通过 const ref 更改原始变量,就像 OP 对 ri 所做的那样。
  • 我每次都“cri”
【解决方案2】:

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

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

在您的示例中,当您执行 int &amp;ri = i; 时,ri 在其生命周期内都绑定到 i。当您执行ri = j; 时,您只是将j 的值分配给riri 仍然是对 i 的引用!它的结果与您改写 i = j;

的结果相同

如果您很好地理解指针,那么请始终将引用视为T* const 的类比解释,其中T 是任何类型。

【讨论】:

    【解决方案3】:

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

    ri=j;
    

    效果和

    一样
    i = j;
    

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

    【讨论】:

      【解决方案4】:

      执行ri = j; 时,您没有重新分配引用。您实际上是在将j 分配给i。尝试在该行之后打印i,您会看到i 的值发生了变化。

      【讨论】:

        【解决方案5】:

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

        在 C++ 中引用的一个有用的口头禅是引用它们所引用的对象。您对其所做的任何更改都是更改他们所指的内容。使用咒语你可能会看到当你做ri = j时发生了什么,我现在 j。

        【讨论】:

          【解决方案6】:

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

          【讨论】:

            【解决方案7】:

            简单来说,

            ri = j;

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-04-10
              • 2019-09-07
              • 1970-01-01
              • 2020-09-05
              • 2021-06-28
              • 1970-01-01
              相关资源
              最近更新 更多