Почему параметры, передаваемые по ссылке в C ++, не требуют оператора разыменования? - PullRequest
7 голосов
/ 22 сентября 2011

Я новичок в сообществе C ++, и у меня есть простой вопрос о том, как C ++ передает переменные по ссылке на функции.

Когда вы хотите передать переменную по ссылке в C ++, вы добавляете & на любой аргумент, который вы хотите передать по ссылке.Почему, когда вы присваиваете значение переменной, передаваемой по ссылке, вы говорите variable = value; вместо *variable = value?

void add_five_to_variable(int &value) {
    // If passing by reference uses pointers,
    // then why wouldn't you say *value += 5?
    // Or does C++ do some behind the scene stuff here?
    value += 5; 
} 

int main() {

  int i = 1;
  add_five_to_variable(i);
  cout << i << endl; // i = 6

  return 0;
}

Если C ++ использует указатели, чтобы сделать это с помощью закулисной магии, почему не нужны разыменования, как с указателями?Любое понимание будет высоко ценится.

Ответы [ 5 ]

5 голосов
/ 22 сентября 2011

Когда вы пишете,

int *p = ...;
*p = 3;

Это синтаксис для присвоения 3 объекту, указанному указателем p.Когда вы пишете,

int &r = ...;
r = 3;

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

Таким образом, можно сказать, что разыменование происходит автоматически, когда это необходимо.

2 голосов
/ 22 сентября 2011

Когда вы передаете объект функции по ссылке, вы манипулируете объектом непосредственно в функции, не обращаясь к его адресу, как с указателями. Таким образом, манипулируя этой переменной, вы не хотите разыменовывать ее с помощью синтаксиса *variable. Это хорошая практика для передачи объектов по ссылке, потому что:

  • Ссылка не может быть переопределена для указания на другой объект
  • Это не может быть нулем. Вы должны передать действительный объект этого типа в функцию

То, как компилятор выполняет «передачу по ссылке», не очень важно в вашем случае.

Статья в Википедии - хороший ресурс.

2 голосов
/ 22 сентября 2011

C ++ использует закулисные указатели, но скрывает от вас все эти сложности.Передача по ссылке также позволяет избежать всех проблем, связанных с недействительными указателями.

1 голос
/ 22 сентября 2011

Есть два вопроса в одном, кажется:

  • один вопрос о синтаксисе: разница между указателем и ссылкой
  • другой вопрос о механике и реализации:представление памяти ссылки

Давайте обратимся к двум по отдельности.

Синтаксис ссылок и указателей

Указатель, концептуально,«знак» (как дорожный знак) к объекту.Он допускает 2 вида действий:

  • действия над указателем (или указанным объектом)
  • действия над самим указателем

* operator*и operator-> позволяют вам получить доступ к pointee, чтобы отличить его от вашего доступа к самому указателю.

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

Механика ссылки

Стандарт C ++ ничего не говорит о реализации ссылок, он просто намекает на то, что еслиможет компилятор может удалить их.Например, в следующем случае:

int main() {
  int a = 0;
  int& b = a;
  b = 1;
  return b;
}

Хороший компилятор поймет, что b - это просто прокси для a, нет места для сомнений, и, таким образом, просто получит прямой доступ к a и оптимизируетb out.

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

0 голосов
/ 22 сентября 2011

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

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