При выполнении этой программы получаем такой результат
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

Старое значение переменной val: 1

Новое значение переменной val: 10

Итак, рассмотрим объявление параметра i. Его имени предшествует символ"&", который "превращает" переменную i в ссылочный параметр. (Это объявление также используется в прототипе функции.) Инструкция

i = 10;

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

Поскольку переменная i была объявлена как ссылочный параметр, компилятор автоматически передает функции f() адрес аргумента, с которым вызывается эта функция. Таким образом, в функции main () инструкция

f (val) ;                     // Передаем адрес переменной val функции f()..

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

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

// Задание 8.1_4.cpp: определяет точку входа для консольного приложения.

// Демонстрируется версия функции swap() с использованием указателей.

#include "stdafx.h"

#include <iostream>

using namespace std;

// Объявляем функцию swap(), которая использует указатели,

void swap(int &x, int &y);    // Прототип функции

int main()

{

setlocale(LC_ALL, "Russian");

int i, j;

i = 10;

j = 20;

cout << "Исходные значения переменных i и j: ";

cout << i << " " << j << "\n";

swap(j, i);  // Вызываем swap() с адресами переменных i и j.

cout << "Значения переменных i и j после обмена: ";

cout << i << " " << j << "\n";

return 0;

}

// Обмен значениями двух переменных, адресуемых параметрами х и у.

void swap(int &x, int &у)

{

int temp;

// Меняем значения переменных, адресуемых параметрами х и у,

// используя явно заданные операции с указателями.

temp = x;    // Временно сохраняем значение по адресу х.

x = у;             // Помещаем значение, хранимое по адресу у, по адресу x.

у = temp;    // Помещаем значение, хранимое по адресу х, по адресу у.

}

Результаты выполнения этой программы совпадают с результатами запуска предыдущей версии. Опять таки, обратите внимание на то, что объявление х и у ссылочными параметрами избавляет вас от необходимости использовать оператор "*" при организации обмена значениями. Как уже упоминалось, такая "навязчивость" с вашей стороны стала бы причиной ошибки. Поэтому запомните, что компилятор автоматически генерирует адреса аргументов, используемых при вызове функции swap (), и автоматически разыменовывает ссылки х и у.

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

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

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

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

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

// Задание 1.8_5.cpp: определяет точку входа для консольного приложения.

// Возврат ссылки.

#include "stdafx.h"

#include <iostream>

using namespace std;

double&f();  // <— Эта функция возвращает ссылку на double-значение.

double val = 100.0;

int main()

{

setlocale(LC_ALL, "Russian");

double x;

cout << f() << "\n";

x = f();

cout << x << "\n";      // Отображаем значение переменной х.

f() = 99.1;             // Изменяем значение глобальнойпеременной val.

cout << f() << "\n";    // Отображаем новое значение val.

return 0;

}

// Эта функция возвращает ссылку на double-значение.

double &f()

{

return val;  // Возвращаем ссылку на глобальную на переменную val.

}

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

100

100

99.1

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

cout ≪ f() <<"\n";                // Отображаем значение val

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

return val;                           // Возвращаем ссылку на val

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

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

х = f();                      //Присваиваем значение val переменной х.

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

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

f( ) = 99.1 ;               // Изменяем значение глобальной переменной val.

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

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

// Задание 8.1_6.cpp: определяет точку входа для консольного приложения.

// Пример функции, возвращающей ссылку на элемент, массива

#include "stdafx.h"

#include <iostream>

using namespace std;

double &change_it(int i);     // Функциявозвращаетссылку,

double vals[] = { 1.1, 2.2, 3.3, 4.4, 5.5 };

int main()

{

setlocale(LC_ALL, "Russian");

int i;

cout << "Вот исходные значения: ";

for (i = 0; i<5; i++)

       cout << vals[i] <<" ";

cout << "\n";

change_it(1) - 5298.23; // Изменяем 2-йэлемент.

change_it(3) = -98.8;   // Изменяем 4-йэлемент.

cout << "Вот измененные значения: ";

for (i = 0; i<5; i++)

       cout << vals[i] <<" ";

cout << "\n";

return 0;

}

double &change_it(int i)

{

return vals[i];         // Возвращаем ссылку на i-й элемент.

}

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

Дата: 2019-05-29, просмотров: 141.