Вот измененные значения: 1.1 5298.23 3.3 -98.8 5.5
Давайте разберемся, как они были получены. Функция change_it() объявлена как возвращающая ссылку на значение типа double. Говоря более конкретно, она возвращает ссылку на элемент массива vals, который задан ей в качестве параметра i. Таким образом, при выполнении следующей инструкции функции main()
change_it(1) = 5298.23; // Изменяем 2-й элемент.
функция change_it() возвращает ссылку на элемент vals[1]. Через эту ссылку элементу vals[1] теперь присваивается значение 5298,23. Аналогичные события происходят при выполнении и этой инструкции.
change_it(3) = -98.8; // Изменяем 4-й элемент.
Поскольку функция change_it() возвращает ссылку на конкретный элемент массива vals, ее можно использовать в левой части инструкции для присвоения нового значения соответствующему элементу массива.
Однако, организуя возврат функцией ссылки, необходимо позаботиться о том, чтобы объект, на который она ссылается, не выходил за пределы действующей области видимости. Например, рассмотрим такую функцию.
// Здесь ошибка: нельзя возвращать ссылку
// на локальную переменную.
int &f()
{
int i=10;
return i;
}
При завершении функции f() локальная переменная i выйдет за пределы области видимости. Следовательно, ссылка на переменную i, возвращаемая функцией f(), будет неопределенной. В действительности некоторые компиляторы не скомпилируют функцию f() в таком виде, и именно по этой причине. Однако проблема такого рода может быть создана опосредованно, поэтому нужно внимательно отнестись к тому, на какой объект будет возвращать ссылку ваша функция.
Ссылочный тип в качестве типа значения, возвращаемого функцией, можно с успехом применить для создания ограниченного массива. Как вы знаете, при выполнении С++-кода проверка нарушения границ при индексировании массивов не предусмотрена. Это означает, что может произойти выход за границы области памяти, выделенной для массива. Другими словами, может быть задан индекс, превышающий размер массива. Однако путем создания ограниченного, или безопасного, массива выход за его границы можно предотвратить. При работе с таким массивом любой выходящий за установленные границы индекс не допускается для индексирования массива.
Один из способов создания ограниченного массива иллюстрируется в следующей программе.
// Простой способ организации безопасного массива.
#include <iostream>
using namespace std;
int &put(int i); // Помещаем значение в массив.
int get(int i); // Считываем значение из массива.
int vals[10];
int error = -1;
int main()
{
put(0) = 10; // Помещаем значения в массив.
put(1) = 20;
put(9) = 30;
cout << get(0) << ' ';
cout << get(1) << ' ';
cout << get(9) << ' ';
// А теперь специально генерируем ошибку.
put(12) =1; // Индекс за пределами границ массива.
return 0;
}
// Функция занесения значения в массив.
int &put(int i)
{
if(i>=0 && i<10)
return vals[i]; // Возвращаем ссылку на i-й элемент.
else {
cout << "Ошибка нарушения границ!\n";
return error; // Возвращаем ссылку на error.
}
}
// Функция считывания значения из массива.
int get(int i)
{
if(i>=0 && i<10)
return vals[i]; // Возвращаем значение i-го элемента.
else {
cout << "Ошибка нарушения границ!\n";
return error; // Возвращаем значение переменной error.