Урок №88. Ссылки

  Юрий  | 

    | 

  Обновл. 27 мая 2019  | 

 22579

До этого момента мы успели рассмотреть два основных типа переменных:

   обычные переменные, которые хранят значения напрямую;

   указатели, которые хранят адрес другого значения (или null), для доступа к которым выполняется операция разыменования указателя.

Ссылки — это третий базовый тип переменных.

Ссылки

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

   Ссылки на неконстантные значения (обычно их называют просто «ссылки» или «неконстантные ссылки»), которые мы обсудим в этом уроке.

   Ссылки на константные значения (обычно их называют «константные ссылки»), которые мы обсудим в следующем уроке.

   В C++11 добавлены ссылки r-value, о которых мы поговорим уже в следующих главах.

Ссылка (на неконстантное значение) объявляется с использованием амперсанда (&) между типом данных и именем ссылки:

В этом контексте амперсанд не означает «оператор адреса», он означает «ссылка на».

Ссылки в качестве псевдонимов


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

Результат выполнения программы выше:

9
10

В примере выше ref и value обрабатываются как одно целое. Использование оператора адреса с ссылкой приведёт к возврату адреса значения, на которое ссылается ссылка:

Краткий обзор l-value и r-value

В уроке №10 мы уже рассматривали, что такое l-value и r-value. l-value — это объект, который имеет определённый адрес памяти (например, переменная x) и сохраняется за пределами одного выражения. r-value — это временное значение без определённого адреса памяти и с областью видимости выражения (т.е. сохраняется в пределах одного выражения). В качестве r-values могут быть как результаты выражения (например, 2 + 3), так и литералы.

Инициализация ссылок


Ссылки должны быть инициализированы при создании:

В отличие от указателей, которые могут содержать нулевое значение, ссылки нулевыми быть не могут.

Ссылки на неконстантные значения могут быть инициализированы только неконстантными l-values. Они не могут быть инициализированы константными l-values или r-values:

Обратите внимание, во втором случае вы не можете инициализировать неконстантную ссылку константным объектом. В противном случае вы бы могли изменить значение константного объекта через ссылку, что уже является нарушением понятия «константа».

После инициализации изменить объект, на который указывает ссылка — нельзя. Рассмотрим следующий фрагмент кода:

Обратите внимание, во втором стейтменте (ref = value2;) выполняется не то, что вы могли бы ожидать! Вместо переприсваивания ref (ссылаться на переменную value2), значение из value2 присваивается переменной value1 (на которое и ссылается ref).

Ссылки в качестве параметров в функциях

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

В уроке №82 мы говорили о том, что передача аргумента-указателя в функцию, позволяет функции при разыменовании этого указателя напрямую изменять значение аргумента.

Ссылки работают аналогично. Поскольку ссылка-параметр — это псевдоним аргумента, то функция, использующая ссылку-параметр, может изменять аргумент, переданный ей, также напрямую:

Результат выполнения программы выше:

7
8

Когда аргумент x передаётся в функцию, то параметр функции ref становится ссылкой на аргумент x. Это позволяет функции изменять значение x непосредственно через ref! Обратите внимание, переменная x не обязательно должна быть ссылкой.

Совет: Передавайте аргументы в функцию через неконстантные ссылки-параметры, если они должны быть изменены функцией в дальнейшем.

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

Ссылки как более лёгкий способ доступа к данным


Второе (гораздо менее используемое) применение ссылок заключается в более лёгком способе доступа к вложенным данным. Рассмотрим следующую структуру:

Предположим, что нам нужно работать с полем value1 структуры Something переменной other структуры Other (звучит сложно, но такое также встречается на практике). Обычно доступ к этому полю осуществлялся бы через other.something.value1. А что, если нам нужно неоднократно получать доступ к этому члену? Код может стать несколько громоздким и беспорядочным. Ссылки же предоставляют более лёгкий способ доступа к данным:

Таким образом, следующие два стейтмента идентичны:

Ссылки позволяют сделать ваш код более чистым и понятным.

Ссылки vs. Указатели

Ссылка — это тот же указатель, который неявно разыменовывается при доступе к значению, на которое он указывает (под капотом ссылки реализованы с помощью указателей). Таким образом, в следующем коде:

*ptr и ref обрабатываются одинаково. Т.е. это одно и то же:

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

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

Заключение

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

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (124 оценок, среднее: 4,89 из 5)
Загрузка...

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *