Объявление ссылочных параметров



 

В изданной в 1986 г. книге Язык программирования C++ (в которой был впервые описан синтаксис C++) Бьерн Страуструп представил стиль объявления ссылочных параметров, одобренный другими программистами. В соответствии с этим стилем оператор "&" связывается с именем типа, а не с именем переменной. Например, вот как выглядит еще один способ записи прототипа функции swap() .

 

 

Нетрудно заметить, что в этом объявлении символ "&" прилегает вплотную к имени типа int , а не к имени переменной х .

Некоторые программисты определяют в таком стиле и указатели, связывая символ "*" с типом, а не с переменной, как в этом примере.

 

 

Приведенные объявления отражают желание некоторых программистов иметь в C++ отдельный тип ссылки или указателя. Но дело в том, что подобное связывание символа "&" или "*" с типом (а не с переменной) не распространяется, в соответствии с формальным синтаксисом C++, на весь список переменных, приведенных в объявлении, что может привести к путанице. Например, в следующем объявлении создается один указатель (а не два) на целочисленную переменную.

 

 

Здесь b объявляется как целочисленная переменная (а не как указатель на целочисленную переменную), поскольку, как определено синтаксисом C++, используемый в объявлении символ "*" или "&" связывается с конкретной переменной, которой он предшествует, а не с типом, за которым он следует.

Важно понимать, что для С++‑компилятора абсолютно безразлично, как именно вы напишете объявление: int *р или int* р . Таким образом, если вы предпочитаете связывать символ "*" или "&" с типом, а не переменной, поступайте, как вам удобно. Но, чтобы избежать в дальнейшем каких‑либо недоразумений, в этой книге мы будем связывать символ "*" или "&" с именем переменной, а не с именем типа.

Важно! В языке С ссылки не поддерживаются. Поэтому единственный способ обеспечить в языке С вызов по ссылке состоит в использовании указателей, как было показано выше (см. первую версию функции swap()). Преобразуя С‑код в С++‑код, вам стоит вместо параметров‑указателей использовать, где это возможно, ссылки.

 

Возврат ссылок

 

Функция может возвращать ссылку. В программировании на C++ предусмотрено несколько применений для ссылочных значений, возвращаемых функциями. Сейчас мы продемонстрируем только некоторые из них, а другие рассмотрим ниже в этой книге, когда познакомимся с перегрузкой операторов.

Если функция возвращает ссылку, это означает, что она возвращает неявный указатель на значение, передаваемое ею в инструкции return . Этот факт открывает поразительные возможности: функцию, оказывается, можно использовать в левой части инструкции присваивания! Например, рассмотрим следующую простую программу.

 

 

Вот как выглядят результаты выполнения этой программы.

 

 

Рассмотрим эту программу подробнее. Судя по прототипу функции f() , она должна возвращать ссылку на double ‑значение. За объявлением функции f() следует объявление глобальной переменной val , которая инициализируется значением 100 . При выполнении следующей инструкции выводится исходное значение переменной val .

 

 

После вызова функция f() возвращает ссылку на переменную val . Поскольку функция f() объявлена с "обязательством" вернуть ссылку, при выполнении строки

 

 

автоматически возвращается ссылка на глобальную переменную val . Эта ссылка затем используется инструкцией cout для отображения значения val .

При выполнении строки

 

 

ссылка на переменную val , возвращенная функцией f() , используется для присвоения значения val переменной newval .

А вот самая интересная строка в программе.

 

 

При выполнении этой инструкции присваивания значение переменной val становится равным числу 99,1 . И вот почему: поскольку функция f() возвращает ссылку на переменную val , эта ссылка и является приемником инструкции присваивания. Таким образом, значение 99,1 присваивается переменной val косвенно, через ссылку на нее, которую возвращает функция f() .

Наконец, при выполнении строки

 

 

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

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

 

 

Эта программа изменяет значения второго и четвертого элементов массива vals . Результаты ее выполнения таковы.

 

 

Давайте разберемся, как они были получены. Функция change_it() объявлена как возвращающая ссылку на значение типа double . Говоря более конкретно, она возвращает ссылку на элемент массива vals , который задан ей в качестве параметра i . Таким образом, при выполнении следующей инструкции функции main()

 

 

функция change_it() возвращает ссылку на элемент vals[1] . Через эту ссылку элементу vals[1] теперь присваивается значение 5298,23 . Аналогичные события происходят при выполнении и этой инструкции.

 

 

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

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

 

 

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

 


Дата добавления: 2018-09-22; просмотров: 261; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!