简体   繁体   中英

Why can I assign a new value to a reference, and how can I make a reference refer to something else?

I have couple of questions related to usage of references in C++.

  1. In the code shown below, how does it work and not give a error at line 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. How can a reference q be reinitialized to something else?

    2. Isn't the string literal, p = "Hello" , a constant or in read-only space? So if we do,

       q = "World";

      wouldn't the string at p which is supposed to be constant be changed?

  2. I have read about C++ reference type variables as they cannot be reinitialized or reassigned, since they are stored 'internally' as constant pointers. So a compiler would give a error.

    But how actually a reference variable can be reassigned?

     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 am trying to get hold of this reference, and in that maybe missed some key things related, so these questions.

So any pointers to clear this up, would be useful.

    • a) It cannot, the line you quote doesn't change the reference q , it changes p .
    • b) No the literal is constant, but p is a pointer which points at a literal. The pointer can be changed, what is being pointed to cannot. q = "world"; makes the pointer p point to something else.
  1. You seem to think that this code

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

    is reassigning a reference, but it isn't. It's assigning the value of k to i , j still refers to i . I would guess that this is your major misunderstanding.

An important detail about references that I think you're missing is that once the reference is bound to an object, you can never reassign it. From that point forward, any time you use the reference, it's indistinguishable from using the object it refers to. As an example, in your first piece of code, when you write

q = "World";

Since q is a reference bound to p , this is equivalent to writing

p = "World";

Which just changes where p is pointing, not the contents of the string it's pointing at. (This also explains why it doesn't crash!)

As for your second question, references cannot be reassigned once bound to an object. If you need to have a reference that can change its referent, you should be using a pointer instead.

Hope this helps!

a) How can a reference q be reinitialized to something else?

It cannot be!

An reference variable remains an alias to which it was initialized at time of creation.


b)Isn't the string literal, p = "Hello", a constant/in read only space. So if we do,
No it doesn't.

char* &q = p;

Here q is an reference to pointer of the type char p . The string here is constant put the pointer is not, it can be pointed to another string, and the reference is alias to this pointer not the string literal so it is valid.


c) Second question I have is I have read about C++ reference type variables as they cannot be reinitialized/reassigned, since they are stored 'internally' as constant pointers. So a compiler would give a error.

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

Does not reassign the reference. it changes the value of the variable to which it was alias.

In this case it changes the value of i to k

Treat reference as an alias name and I hope the world of reference will much easier to understand.

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.

So, p = 5 and q = 5 will be all the same.

In your example,

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.

So all in all, p & q are names of the entity/object (memory).

So, if you assign q something, it reflects in p too. Coz it is same as the assignment to p. So q = "World", means p too now points to "World". ie the Memory location which p & q both refer to - holds the address of first character of "World".

I hope the second question need not be answered if you understand the notion of reference as an alias.

It is to be noted that since C++20, it is possible to change the reference held by a reference variable inside a class, using placement new , like in the following example taken from 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!
}

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM