14.5  Ссылка в качестве возвращаемого значения функции

Функция может возвращать ссылку. Возвращение ссылки может оказаться полезным при перегрузке операторов определенных типов. Кроме этого, возвращение ссылки позволяет использовать функцию слева в инструкции присваивания. Это приводит к важному и неожиданному результату. Рассмотрим примеры.

Пример 1

// Простая программа с функцией, которая возвращает ссылку:

#include <iostream>

using namespace std;

int x;

int &f()

{

return x;

}

int main()

{

f() = 100; // Присваивание 100 ссылке, возвращаемой функцией f()

cout<<x<<endl;

return 0;

}

Здесь функция f() объявляется возвращающей ссылку на целое. Внутри тела функции инструкция return x; не возвращает значение глобальной переменной х, она автоматически возвращает адрес переменной х (в виде ссылки). Таким образом, внутри функции main() инструкция f() = 100; заносит значение 100 в переменную х, поскольку функция f() уже возвратила ссылку на нее.

Функция f() возвращает ссылку. Когда функция f() указана слева в инструкции присваивания, то, таким образом, слева оказывается ссылка на объект, которую возвращает эта функция. Поскольку функция f() возвращает ссылку на переменную х (в данном примере), то эта переменная х и получает значение 100.

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

Пример 2

// Возвращение ссылки на целое

int &f()

{

int х; // х – локальная переменная

return x; // возвращение ссылки на х

}

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

Возвращение функцией ссылки может быть полезно при перегрузке операторов ввода и вывода. Например:

#include <iostream>

// Объявление класса time

class time

{

// Закрытые члены класса

private:

int h, m, s;

// Общедоступные члены класса

public:

// Функция для подсчета секунд

void count_seconds()

{

cout<<"Прошло секунд: "<<h*3600+m*60+s<<endl;

}

// Конструктор по умолчанию

time()

{

h=12;

m=12;

s=12;

}

// Конструктор инициализирующий

time (int tmp)

{

cout<<"Введите расчетное время (чч[0-23], мм[0-59], сс[0-59]):"<<endl;

cin>>h;

cin>>m;

cin>>s;

}

// Дружественная функция-перегрузка оператора <<

friend ostream & operator << (ostream &os, time &t)

{

os<<"Заданное время: "<<t.h<<‘:'<<t.m<<‘:'<<t.s<<endl; return os;

}

// Дружественная функция-перегрузка оператора >>

friend istream & operator >> (istream &is, time &t)

{

cout<<"Введите час: ";

is>>t.h;

cout<<"Введите минуты: ";

is>>t.m;

cout<<"Введите секунды: ";

is>>t.s;

return is;

}

};

void main ()

{

cout<<"Создание объекта №1 с помощью конструктора без параметров:"<<endl;

time t1;

cout<<t1<<endl;

cout<<"Ввод значений для объекта №1:"<<endl;

cin>>t1;

cout<<t1<<endl;

}