Вернуться по ссылке в C ++ - PullRequest
1 голос
/ 05 июля 2011
#include<iostream>
using namespace std;

int& add() {

    static int a;
    a++;
    cout<<"\na="<<a;
    return a;
}

int main {

   int x,y,m;
   int &z = add(); //it behaves as a reference to "a" which is a static variable
   x=add();//why does it work correctly
   y=add();//why does it work correctly
   z++;
   m=add();//why does it work correctly
   cout<<"\nx="<<x<<"\ny="<<y<<"\nz="<<z<<"\nm="<<m;
   return 0;
}

output:
a=1
a=2
a=3
a=5
x=2
y=3
z=5
m=5

Что происходит внутри x, y, m & z

Ответы [ 7 ]

3 голосов
/ 05 июля 2011
int &z = add();

z является ссылкой на статическую переменную a. Отныне a и z являются синонимами. Оба они указывают на одну и ту же область памяти.

int x;
x = add();

x является независимой ячейкой памяти. Из-за присваивания x будет содержать все, что add() вернет в точке вызова. Так работают y и m.

3 голосов
/ 05 июля 2011
int main{
    int x,y,m;      // declare three ints:  x,y,m, all unassigned
    int &z = add(); // a is incremented to 1, z is a reference to a
    x=add();        // add() returns a reference to a, x copies the value of a
    y=add();        // same as above
    z++;            // increments a, since z is a reference to a
    m=add();        // same as x and y, copies the value of a
    cout<<"\nx="<<x<<"\ny="<<y<<"\nz="<<z<<"\nm="<<m;
    return 0;
}

, поэтому вы вызываете add() три раза подряд, что увеличивает a до 1, 2, 3 (и печатает значение каждый раз.

z является ссылкой надействительные a.

x, y и m являются копиями значения a, когда было выполнено присваивание. Итак, x равно 2, y равно 3, мы пропускаем4, выполнив z++, а затем m равно 5.

2 голосов
/ 05 июля 2011

Ссылка - это другое имя, псевдоним для некоторого объекта.Он действует так, как если бы он был объектом.

Когда add() возвращает ссылку на a, он ведет себя так, как если бы возвращенное значение было a.

Таким образом, код

x = add();

ведет себя так, как если бы он был

a++;
x = a;

Таким образом, он фиксирует значение, которое a имеет в тот момент.

С другой стороны, код

int& z = add();

ведет себя так же, как

a++;
int& z = a;

Где z становится другим именем для a.Использование a или z отныне не имеет значения, это означает то же самое.Все еще есть только одно значение, но оно имеет два имени.Мы можем использовать любой из них, чтобы прочитать или обновить его.

Это похоже на то, когда мы используем Боба для ссылки на парня по имени Роберт - другое имя для той же вещи.

2 голосов
/ 05 июля 2011

x, y и m являются просто переменными, поэтому они получают любое значение в a во время вызова add, и все.Если вы измените значения любой из этих переменных, это не повлияет на значение a.Поскольку z является ссылкой, это «указатель» (в некотором смысле) на статическую переменную a, поэтому изменение z фактически изменит a.

1 голос
/ 05 июля 2011

Хорошо, давайте рассмотрим эту маленькую программу

int& add() 
{
   static int a;
   a++;
   cout<<"\na="<<a;
   return a;
}

static int a объявляет переменную. Статический в этом контексте означает, что есть только место для хранения, и это место используется всякий раз, когда вызывается add. Таким образом, a похож на глобальную переменную, доступ к которой возможен только внутри add.

Возвращаемое значение является справочным. Большинство компиляторов используют указатель внутри для представления ссылки. Здесь вы видите, что возвращается ссылка на статическую переменную a. Любой может изменить его, получив ссылку.

a ++ и cout просты - здесь больше нет комментариев.

int main{
    int x,y,m;      // declare three ints:  x,y,m, all unassigned
    int &z = add(); // a is incremented to 1, z is a reference to a
    x=add();        // add() returns a reference to a, x copies the value of a
    y=add();        // same as above
    z++;            // increments a, since z is a reference to a
    m=add();        // same as x and y, copies the value of a
    cout<<"\nx="<<x<<"\ny="<<y<<"\nz="<<z<<"\nm="<<m;
    return 0;
}

int & z = add (); вызывает добавление - это означает, что увеличивается. Теперь z является псевдонимом статической переменной a, так как она использует ссылку. х = Add (); снова увеличьте a, но теперь скопируйте значение a, поскольку x имеет тип не int &, а тип int. у - то же самое. z ++: поскольку z является псевдонимом для a - увеличивает a без печати через cout.

m = add (): увеличить a, скопировать int m, например, x и y.

Вывод будет простым, если вы поймете, почему x, y, m являются копиями, а z - псевдонимом.

Есть еще вопросы?

привет

Tobias

1 голос
/ 05 июля 2011

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

То, что делает C ++, просто избавляет вас от добавленияссылается на синтаксис (унарный *), когда вам нужно значение, и позволяет использовать . вместо -> для доступа к членам указанного структурированного типа.

Обратите внимание, что существует общий анти-шаблонв C ++, который использует const X&, как если бы это был более умный способ, чем просто X для параметров функции.Пожалуйста, никогда не забывайте, что ссылка - это, в основном, указатель, поэтому указанный объект может изменяться или даже исчезать во время использования (const не означает, что объект не изменяется, просто вы не можете изменить его , используя эту ссылку ).

См. этот ответ для более подробного описания того, на что следует обращать внимание при использовании ссылок вместо значений.

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

Переводя ваш код в то, что действительно происходит (перебирая указатель), вы получаете

#include<iostream>
using namespace std;

int* add() {
    static int a;
    a++;
    cout << "\na=" << a;
    return &a; // we're returning a pointer to our static variable
}

int main(int argc, const char *argv[]) {
   int x,y,m;
   int *z = add(); // points to "a" which is a static variable
   x = *add();     // just get the current value of (incremented) a
   y = *add();     // same here, of course now different from x
   (*z)++;         // incrementing a from outside the function (we've a pointer!)
   m = *add();     // once again just reading current incremented value
   cout << "\nx=" << x << "\ny=" << y<< "\nz=" << (*z) << "\nm=" << m;
   return 0;
}
1 голос
/ 05 июля 2011

Мне кажется, вот как это работает:

Ссылки, используемые в контексте, где (значение) ссылочного типа требуется, неявно разыменовываются. Это включает (среди прочего):

  • присвоение переменной
  • передача аргументов функции, объявленной значением
  • передавая функции возвращаемые значения, объявленные значением

В вышеуказанном контексте создается копия ссылочного значения.

Везде, где необходима ссылка, они рассматриваются как ссылки (очевидно, не разыменованные.) Это включает в себя:

  • инициализация ссылки совместимого типа
  • передача аргументов функции, объявленной ссылкой
  • передача возвращаемых значений функции, если она объявлена ​​ссылкой

В этих контекстах копия ссылочного значения не создается. Новая ссылка - это просто новый псевдоним для существующего значения.

Синтаксис для обоих вышеупомянутых контекстов одинаков, поэтому требуется некоторое усилие, чтобы увидеть, что происходит.

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