Почему я могу присвоить ссылку новому значению и как сделать ссылку ссылкой на что-то еще? - PullRequest
28 голосов
/ 24 августа 2011

У меня есть пара вопросов, связанных с использованием ссылок в 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?
    

    Я пытаюсь заполучить эту ссылку, и в этом, возможно, пропущен какой-то ключвещи, связанные с этим, поэтому эти вопросы.

Так что любые указатели, чтобы прояснить это, было бы полезно.

Ответы [ 4 ]

56 голосов
/ 24 августа 2011
    • a) Не может, указанная вами строка не меняет ссылку q, она меняет p.
    • b) Нет, литерал является константой, но p является указателем, который указывает на литерал. Указатель может быть изменен, на что указывает, не может. q = "world"; заставляет указатель p указывать на что-то другое.
  1. Вы, кажется, думаете, что этот код

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

    переназначает ссылку, но это не так. Он присваивает значение k i, j по-прежнему относится к i. Я предполагаю, что это ваше главное недоразумение.

23 голосов
/ 24 августа 2011

Важная деталь в ссылках, которые, по-моему, вам не хватает, заключается в том, что как только ссылка привязана к объекту, вы никогда не сможете переназначить ее. С этого момента, всякий раз, когда вы используете ссылку, она неотличима от использования объекта, на который она ссылается. Например, в вашем первом куске кода, когда вы пишете

q = "World";

Поскольку q является ссылкой, привязанной к p, это эквивалентно записи

p = "World";

Что просто меняет, куда указывает p, а не содержимое строки, на которую он указывает. (Это также объясняет, почему он не падает!)

Что касается вашего второго вопроса, ссылки не могут быть переназначены после привязки к объекту. Если вам нужна ссылка, которая может изменить его референт, вместо этого вы должны использовать указатель.

Надеюсь, это поможет!

3 голосов
/ 25 августа 2011

Относитесь к ссылке как к псевдониму, и я надеюсь, что мир ссылок станет намного проще для понимания.

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. Потому что это так же, как назначение на р. Таким образом, q = "Мир", означает, что p тоже теперь указывает на "Мир". то есть ячейка памяти, на которую ссылаются p & q, - содержит адрес первого символа «World».

Я надеюсь, что на второй вопрос не нужно отвечать, если вы понимаете понятие ссылки как псевдоним.

3 голосов
/ 24 августа 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...