【问题标题】:Why can I assign a new value to a reference, and how can I make a reference refer to something else?为什么我可以为引用分配新值,以及如何使引用引用其他内容?
【发布时间】:2011-11-03 03:03:25
【问题描述】:

我有几个与 C++ 中引用的使用有关的问题。

  1. 在下面显示的代码中,它是如何工作的并且在q = "world";行不报错?

    #include <iostream>
    
    using namespace std;
    
    int main()
    {
      char *p = "Hello";
      char* &q = p;
      cout <<p <<' '<<q <<"\n";
      q = "World"; //Why is there no error on this line
      cout <<p <<' '<<q <<"\n";
    }
    
    1. 如何将引用 q 重新初始化为其他内容?

    2. 字符串文字p = "Hello" 不是常量还是只读空间?所以如果我们这样做,

      q = "World";
      

      p 应该是常量的字符串不会被更改吗?

  2. 我已经阅读了有关 C++ 引用类型变量的信息,因为它们无法重新初始化或重新分配,因为它们“内部”存储为常量指针。所以编译器会报错。

    但实际上如何重新分配引用变量?

    int i;
    
    int &j = i;
    
    int k;
    
    j = k; //This should be fine, but how we reassign to something else to make compiler flag an error?
    

    我正在尝试获取此参考资料,其中可能遗漏了一些相关的关键内容,因此提出了这些问题。

因此,任何清除此问题的指针都会很有用。

【问题讨论】:

    标签: c++ reference


    【解决方案1】:

    需要注意,从 C++20 开始,可以使用placement new更改类中引用变量所持有的引用,就像下面这个取自this SO post的例子:

    struct C {
      int& i; // <= a reference field
      void foo(const C& other) {
        if ( this != &other ) {
          this->~C();
          new (this) C(other); // valid since C++20 even on a class 
                               // with a reference field
        }
      }
    };
    
    int main() {
        int a = 3, b = 5;
        C c1 {.i = a};
        C c2 {.i = b};
        c1.foo(c2); // the inner reference field i inside c1
                    // was referring to a and now refers to b!
    }
    

    代码:http://coliru.stacked-crooked.com/a/4674071ea82ba31b

    【讨论】:

      【解决方案2】:
        • a) 不能,您引用的行不会更改引用 q,它会更改 p
        • b) 不是文字是常量,但p 是一个指向文字的指针。 指针可以更改,所指向的内容不能更改。 q = "world"; 使指针 p 指向别的东西。
      1. 你似乎认为这段代码

        int i;
        int &j = i;
        int k;
        j = k;
        

        正在重新分配引用,但事实并非如此。 它将k 的值分配给ij 仍然指的是i。 我猜这是你的主要误解。

      【讨论】:

      • 准确地说,我的 qns 是并且现在是什么代码会重新分配对其他东西的引用。(这在技术上是不允许的)我在 OP 中提到 j = k;很好,因为我知道它会改变“裁判”的价值。
      【解决方案3】:

      将引用视为别名,我希望引用的世界更容易理解。

      int p; // Declares p as an integer; Defines p & allocates space
      int &q = p ; // Declares a Reference. Though they are symbolically 2 variables,
                   // they essentially refer to same name and same memory location.
      

      所以,p = 5 和 q = 5 都是一样的。

      在你的例子中,

      char *p = "Hello"; // Declares your pointer to "Hello". p has its own existence.
      char* &q = p;  // This now creates a reference (alias) to p with name q.
      

      所以总而言之,p & q 是实体/对象(内存)的名称。

      所以,如果你给 q 赋值,它也会反映在 p 中。因为它与 p 的分配相同。 所以 q = "World",意味着 p 现在也指向 "World"。即 p 和 q 都引用的内存位置 - 保存“世界”的第一个字符的地址。

      如果您将引用的概念理解为别名,我希望不需要回答第二个问题。

      【讨论】:

        【解决方案4】:

        a) 如何将引用 q 重新初始化为其他东西?

        不可能!

        引用变量仍然是在创建时初始化的别名。


        b) 不是字符串文字,p = "Hello",一个常量/只读空间。因此,如果我们这样做,
        不,它不会。

        char* &q = p;
        

        这里的q 是对char p 类型指针的引用。这里的字符串是常量,指针不是,它可以指向另一个字符串,并且引用是这个指针的别名而不是字符串文字,所以它是有效的。


        c) 我遇到的第二个问题是我已经阅读了有关 C++ 引用类型变量的信息,因为它们无法重新初始化/重新分配,因为它们“内部”存储为常量指针。所以编译器会报错。

        int i;
        
        int &j = i;
        
        int k;
        
        j = k; //This should be fine, but how we reassign to something else to make compiler flag an error
        

        不重新分配引用。它改变了作为别名的变量的值。

        在这种情况下,它将i 的值更改为k

        【讨论】:

          【解决方案5】:

          我认为您缺少的关于引用的一个重要细节是,一旦引用绑定到一个对象,您就永远无法重新分配它。从那时起,任何时候你使用引用,它都与使用它所引用的对象没有区别。例如,在您的第一段代码中,当您编写时

          q = "World";
          

          由于q 是绑定到p 的引用,所以这相当于写

          p = "World";
          

          这只是改变p 指向的位置,而不是它指向的字符串的内容。 (这也解释了为什么它不会崩溃!)

          至于您的第二个问题,引用一旦绑定到对象就不能重新分配。如果您需要一个可以更改其所指对象的引用,则应该改用指针。

          希望这会有所帮助!

          【讨论】:

            猜你喜欢
            • 2011-09-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-01-29
            • 2016-03-05
            • 1970-01-01
            • 2023-03-10
            • 2011-05-04
            相关资源
            最近更新 更多