Почему функция не может иметь ссылочный аргумент в C? - PullRequest
6 голосов
/ 17 октября 2010

Например: void foo( int& i ); не допускается.Есть ли причина для этого, или это просто не было частью спецификации?Насколько я понимаю, ссылки обычно реализуются как указатели.В C ++ есть ли функциональное различие (не синтаксическое / семантическое) между void foo( int* i ) и void foo( int& i )?

Ответы [ 6 ]

31 голосов
/ 17 октября 2010

Поскольку ссылки - это функция C ++.

8 голосов
/ 17 октября 2010

Ссылки являются просто синтаксическим уксусом для указателей.Их реализация идентична, но они скрывают тот факт, что вызываемая функция может изменить переменную.Единственный раз, когда они действительно выполняют важную роль, - это сделать возможными другие функции C ++ - на ум приходит перегрузка операторов - и в зависимости от вашей перспективы это может быть также синтаксический уксус.

4 голосов
/ 18 октября 2010

Например: void foo (int & i); не допускается. Есть ли причина для этого, или это просто не было частью спецификации?

Это не было частью спецификации. Синтаксис "type &" для ссылок был введен в C ++.

Насколько я понимаю, ссылки обычно реализуются как указатели. Есть ли в C ++ функциональная разница (не синтаксическая / семантическая) между void foo (int * i) и void foo (int & i)?

Я не уверен, что это квалифицируется как семантическая разница, но ссылки предлагают лучшую защиту от разыменования нулей.

0 голосов
/ 18 октября 2010

Ссылки не присутствовали в C. Однако, C действительно имел то, что равносильно изменяемым аргументам, передаваемым по ссылке. Пример:
int foo (int in, int * out) {return (* out) ++ + in; }
// ...
int x = 1; int y = 2;
x = foo (x, & y);
// x == y == 3.
Однако было распространенной ошибкой забывать разыменовывать «out» при каждом использовании в более сложных функциях foo (). Ссылки на C ++ допускают более плавный синтаксис для представления изменяемых членов замыкания. В обоих языках это может мешать оптимизации компилятора, поскольку несколько символов ссылаются на одно и то же хранилище. (Рассмотрим «foo (x, x)». Теперь не определено, встречается ли «++» после только «* out» или также после «in», поскольку между этими двумя точками нет последовательности, а приращение требуется только для произойдет когда-нибудь после того, как будет взято значение левого выражения.)

Но кроме того, явные ссылки устраняют неоднозначность в двух случаях для компилятора C ++. Указатель, передаваемый в функцию C, может быть изменяемым аргументом или указателем на массив (или многое другое, но эти два адекватно иллюстрируют неоднозначность). Контраст "char * x" и "char * y". (... или не сделать этого, как ожидалось.) Переменная, переданная по ссылке в функцию C ++, однозначно является изменяемым членом замыкания. Если, например, у нас было
// в классе baz
private: int bar (int & x, int & y) {return x - y};
public: int foo (int & x, int & y) {return x + bar (x, y);}
// выход из области действия и блуждание по ...
int a = 1; int b = 2; баз с;
a = c.foo (a, b);
Мы знаем несколько вещей:
bar () вызывается только из foo (). Это означает, что bar () можно скомпилировать так, чтобы два его аргумента находились в кадре стека foo (), а не в его собственном. Это называется copy elision, и это отличная вещь.

Копирование elision становится еще более захватывающим, когда функция имеет вид "T & foo (T &)", компилятор знает, что временное входящее и выходящее время, и компилятор может сделать вывод, что результат может быть создан на месте аргумента. Тогда нет необходимости компилировать временные входные или выходные данные. Foo () может быть скомпилирован, чтобы получить свой аргумент из некоторого вмещающего фрейма стека и записать свой результат непосредственно в какой-либо вмещающий фрейм стека.

недавняя статья о копировании, и (удивительно) она работает еще лучше, если вы передаете по значению в современных компиляторах (и как ссылки на rvalue в C ++ 0x помогут компиляторам пропускать еще больше бессмысленных копий ) см. http://cpp -next.com / archive / 2009/08 / want-speed-pass-by-value / .

0 голосов
/ 18 октября 2010

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

0 голосов
/ 17 октября 2010

Поскольку оператор & имеет только 2 значения в C:

  1. адрес своего операнда (унарный),

  2. и,побитовый оператор AND (двоичный).

int &i; не является допустимым объявлением в C.

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