#cpp #указатели #ссылки
This question already has answers here: Чем отличаются ссылки от указателей в С++ (2 ответа) Закрыт 3 года назад. В чем будет разница, если в функцию передать указатель и ссылку? например #includevoid func(int *a) { *a = 5 } int main() { int a; func(a); std::cout << a; } и #include void func(int &a) { a = 5 } int main() { int a; func(a); std::cout << a; } Программы выведут одно и то же? Ведь и так, и так мы обращаемся к существующему элементу, а не создаем новый.
Ответы
Ответ 1
В принципе, технически разница между указателем и ссылкой лишь в том, что саму ссылку нельзя изменить (а указатель можно). [Вот тут бóльший список отличий.] Кроме этого, разница ещё синтаксическая: с ссылкой вы обращаетесь как будто это переменная, а с указателем нужно его правильно получать/разыменовывать: void func(int *a) { *a = 5; } int main() { int a; func(&a); cout << a; } Других технических отличий нет, и результат будет одинаковый. Но разница на самом деле не в синтаксисе, а в смысле, в семантике. Указатель может означать всё, что угодно. Он в C и C++ означает строку, ассив, адрес переменной, передачу переменной по ссылке и ещё кучу всяких вещей. А смысл ссылки ровно один — это как бы альтернативное имя (alias) существующей переменной. Поэтому для случаев наподобие того, который вы описали, в C++ уместно использовать ссылку, а не указатель. Хотя, как вы сами видите, с указателем тоже прекрасно работает. И ещё: в чистом C ссылок нет, так что у вас нет другого варианта кроме указателей.Ответ 2
Ответы на ваш вопрос даны выше, разницы в поведении никакой, но хотел бы уточнить несколько нюансов. 1. Пока у вас простые типы разницы никакой (кроме описаной выше в других ответах, например про NULL значение переменной в случае указателя). Но как только дело дойдет до классов появится разница. В случае передачи в функцию указателя на класс то, в зависимости от реализации и решаемых задач, будет иметь место разыменовывание указателя. Сложность этой процедуры будет зависеть от размера класса. Это справделиво в случе разыменовывания всего класса и не касается доступа к отдельным его членам. Например: int c = b->d; //дешево, а A b = *A; //дороже 2. вы можете перегрузить оператор &, а * нет. 3. Указатели не могут принимать временные значения, в то время как const & могут. Например: void f(const &A);.... f(A()); //возможно 4. В целом работа с ссылками проще, поэтому ведут к меньшему числу ошибок Золотое правило с++ программиста: используй ссылки где можешь, а указатели где должен.Ответ 3
Если вы исправите опечатки и включите заголовок #includevoid func(int *a) { *a = 5; ^^ ^ } int main() { int a; func(a); std::cout << a; ^^^^^ } и #include void func(int &a) { a = 5; ^ } int main() { int a; func(a); std::cout << a; ^^^^^ } То вывод будет идентичен. Когда используются указатели, то вы можете передать null-указатель. Например, void func(int *a) { if ( a ) *a = 5; } И функция может быть вызвана как int x; func( &x ); func( nullptr ); Когда же используются ссылки, то ссылка должна указывать на существующий объект.
Комментариев нет:
Отправить комментарий