Чтобы понять, как передача указателя позволяет вручную обеспечить вызов по ссылке, рассмотрим следующую версию функции swap(). (Она меняет значения двух переменных, на которые указывают ее аргументы.)
void swap(int *х, int *у)
{
int temp;
temp = *x; // Временно сохраняем значение, расположенное по адресу х.
*х = *у; // Помещаем значение, хранимое по адресу у, в адрес х.
*у = temp; // Помещаем значение, которое раньше хранилось по адресу х, в адрес у.
}
Здесь параметры *х и *у означают переменные, адресуемые указателями х и у, которые попросту являются адресами аргументов, используемых при вызове функции swap(). Следовательно, при выполнении этой функции будет совершен реальный обмен содержимым переменных, используемых при ее вызове.
Поскольку функция swap() ожидает получить два указателя, вы должны помнить, что функцию swap() необходимо вызывать с адресами переменных, значения которых вы хотите обменять. Корректный вызов этой функции продемонстрирован в следующей программе.
#include <iostream>
using namespace std;
// Объявляем функцию swap(), которая использует указатели.
void swap(int *х, int *у);
int main()
{
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 *y)
{
int temp;
temp = *x; // Временно сохраняем значение, расположенное по адресу х.
*х = *у; // Помещаем значение, хранимое по адресу у, в адрес х.
*у = temp; // Помещаем значение, которое раньше хранилось по адресу х, в адрес у.
}
Результаты выполнения этой программы таковы.
Исходные значения переменных i и j: 10 20
Значения переменных i и j после обмена: 20 10
В этом примере переменной i было присвоено начальное значение 10, а переменной j — 20. Затем была вызвана функция swap() с адресами переменных i и j. Для получения адресов здесь используется унарный оператор Следовательно, функции swap() при вызове были переданы адреса переменных i и j, а не их значения. После выполнения функции swap() переменные i и j обменялись своими значениями.
Ссылочный параметр автоматически получает адрес соответствующего аргумента.
Несмотря на возможность "вручную" организовать вызов по ссылке с помощью оператора получения адреса, такой подход не всегда удобен. Во-первых, он вынуждает программиста выполнять все операции с использованием указателей. Во-вторых, вызывая функцию, программист должен не забыть передать ей адреса аргументов, а не их значения. К счастью, в C++ можно сориентировать компилятор на автоматическое использование вызова по ссылке (вместо вызова по значению) для одного или нескольких параметров конкретной функции. Такая возможность реализуется с помощью ссылочного параметра (reference parameter). При использовании ссылочного параметра функции автоматически передается адрес (а не значение) аргумента. При выполнении кода функции, а именно при выполнении операций над ссылочным параметром, обеспечивается его автоматическое разыменование, и поэтому программисту не нужно использовать операторы, работающие с указателями.
Ссылочный параметр объявляется с помощью символа который должен предшествовать имени параметра в объявлении функции. Операции, выполняемые над ссылочным параметром, оказывают влияние на аргумент, используемый при вызове функции, а не на сам ссылочный параметр.