Читаем Программирование полностью

Этот код работает, но при первом вызове функции print() будет скопирован десяток чисел типа double (вероятно, 80 байт), при втором — миллионы чисел типа double (вероятно, восемь мегабайт), а при третьем количество копируемых чисел неизвестно. Возникает вопрос: “Зачем вообще что-то копировать?” Мы же хотим распечатать вектор, а не скопировать его. Очевидно, нам нужен способ передачи переменных функциям без их копирования. Например, если вы получили задание составить список книг, находящихся в библиотеке, то совершенно не обязательно приносить копии всех книг домой — достаточно взять адрес библиотеки, пойти туда и просмотреть все книги на месте.

Итак, нам необходим способ передачи функции print() “адреса” вектора, а не копии вектора. “Адрес” вектора называется ссылкой (reference) и используется следующим образом:

void print(const vector& v) // передача по константной ссылке

{

  cout << "{ ";

  for (int i = 0; i

    cout << v[i];

    if (i!=v.size()–1) cout << ", ";

  }

  cout << " }\n";

}

Символ & означает ссылку, а ключевое слово const предотвращает случайную модификацию аргумента в функции print(). Кроме объявления аргумента, все остальное без изменений. Правда, теперь все операции будут производиться не над копией, а над самим аргументом, полученным по ссылке. Такие аргументы называются ссылками, потому что они ссылаются на объекты, определенные вне функции. Вызов функции print() остается точно таким же, как и раньше.

void f(int x)

{

  vector vd1(10);      // небольшой вектор

  vector vd2(1000000); // большой вектор

  vector vd3(x);       // вектор неопределенного размера

  // ...заполняем векторы vd1, vd2, vd3 значениями...

  print(vd1);

  print(vd2);

  print(vd3);

}

Этот механизм можно проиллюстрировать графически.

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

void print(const vector& v) // передача по константной ссылке

{

  // ...

  v[i] = 7; // ошибка: v — константа (т.е. не может изменяться)

  // ...

}

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

int my_find(vector vs, string s); // передача по значению:

                                          // копия

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

// передача по ссылке: без копирования, доступ только для чтения

int my_find(const vector& vs, const string& s); 

<p id="AutBody_Root145"><strong>8.5.5. Передача параметров по ссылке</strong></p>

 А что делать, если мы хотим, чтобы функция модифицировала свои аргументы? Иногда это очень нужно. Например, мы можем написать функцию init(), которая должна присваивать начальные значения элементам вектора.

void init(vector& v) // передача по ссылке

{

  for (int i = 0; i

}

void g(int x)

{

  vector vd1(10);      // небольшой вектор

  vector vd2(1000000); // большой вектор

  vector vd3(x);       // вектор неопределенного размера

  init(vd1);

  init(vd2);

  init(vd3);

}

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

Рассмотрим ссылки более подробно. Ссылка — это конструкция, позволяющая пользователю объявлять новое имя объекта. Например, int& — это ссылка на переменную типа int. Это позволяет нам написать следующий код:

int i = 7;

int& r = i; // r — ссылка на переменную i

r = 9;      // переменная i становится равной 9

i = 10;

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже