Напомним, что операции со ссылками — это фактически операции с объектами, к которым они привязаны (см. раздел 2.3.1):
int n = 0, i = 42;
int &r = n; //
r = 42; //
r = i; //
i = r; //
Ссылочные параметры используют это поведение. Обычно они применяются, чтобы позволить функции изменить значение одного или нескольких аргументов.
Для примера можно переписать программу reset
из предыдущего раздела так, чтобы использовать ссылку вместо указателя:
//
void reset(int &i) //
//
{
i = 0; //
}
Подобно любой другой ссылке, ссылочный параметр связывается непосредственно с объектом, которым он инициализируется. При вызове этой версии функции reset()
параметр i
будет связан с любым переданным ей объектом типа int
. Как и с любой ссылкой, изменения, сделанные с параметром i
, осуществляются с объектом, на который она ссылается. В данном случае этот объект — аргумент функции reset()
.
Когда вызывается эта версия функции reset()
, объект передается непосредственно; поэтому нет никакой необходимости в передаче его адреса:
int j = 42;
reset(j); //
cout << "j = " << j << endl; //
В этом вызове параметр i
— это только другое имя переменной j
. Любое использование параметра i
в функции reset()
фактически является использованием переменной j
.
Копирование объектов больших классов или больших контейнеров снижает эффективность программы. Кроме того, некоторые классы (включая классы IO) не допускают копирования. Для работы с объектами, тип которых не допускает копирования, функции должны использовать ссылочные параметры.
В качестве примера напишем функцию сравнения длин двух строк. Поскольку строки могут быть очень длинными и их копирования желательно избежать, сделаем параметры ссылками. Так как сравнение двух строк не подразумевает их изменения, сделаем ссылочные параметры константами (см. раздел 2.4.1):
//
bool isShorter(const string &s1, const string &s2) {
return s1.size() < s2.size();
}
Как будет продемонстрировано в разделе 6.2.3, для не подлежащих изменению ссылочных параметров функции должны использовать ссылки на константу.
const
.
Функция может возвратить только одно значение. Но что если функции нужно возвратить больше одного значения? Ссылочные параметры позволяют возвратить несколько результатов. В качестве примера определим функцию find_char()
, которая возвращает позицию первого вхождения заданного символа в строке. Функция должна также возвращать количество этих символов в строке.
Как же определить функцию, возвращающую и позицию, и количество вхождений? Можно было бы определить новый тип, содержащий позицию и количество. Однако куда проще передать дополнительный ссылочный аргумент, содержащий количество вхождений:
//
//
string::size_type find_char(const string &s, char c,
string::size_type &occurs) {
auto ret = s.size(); //
occurs = 0; //
for (decltype(ret) i = 0; i != s.size(); ++i) {
if (s[i] == c) {
if (ret == s.size())
ret = i; //
++occurs; //
}
}
return ret; //
}