Вход/Регистрация
Программирование. Принципы и практика использования C++ Исправленное издание
вернуться

Страуструп Бьерн

Шрифт:

Простейший способ передать аргумент функции заключается в пересылке копии его значения. Аргумент функции
f
является локальной переменной, которая инициализируется при каждом ее вызове. Рассмотрим пример.

// передача по значению (функция получает копию передаваемого

// значения)

int f(int x)

{

x = x+1; // присваиваем локальной переменной x новое значение

return x;

}

int main

{

int xx = 0;

cout << f(xx) << endl; // вывод: 1

cout << xx << endl; // вывод: 0; функция f не изменяет xx

int yy = 7;

cout << f(yy) << endl; // вывод: 8

cout << yy << endl; // вывод: 7; функция f не изменяет yy

}

Поскольку в функцию передается копия, инструкция

x=x+1
в функции
f
не изменяет значения переменных
xx
и
yy
, передаваемых ей при двух вызовах. Передачу аргумента по значению можно проиллюстрировать следующим образом.

Передача по значению представляет собой довольно простой механизм, а ее стоимость определяется стоимостью копирования значения.

8.5.4. Передача параметров по константной ссылке

Передача по значению проста, понятна и эффективна, если передаются небольшие значения, например переменные типа

int
,
double
или
Token
(см. раздел 6.3.2). А что если передаваемое значение велико и представляет собой изображение (занимающее несколько миллионов бит), большую таблицу чисел (например, несколько тысяч целых чисел) или длинную строку (например, сотни символов)? Тогда копирование оказывается очень затратным механизмом. Не стоит слишком сильно беспокоиться о стоимости выполняемых операций, но делать ненужную работу также не следует, так как это свидетельствует о плохом воплощении идеи, которую мы хотим реализовать. Например, можно написать следующую функцию, выводящую на экран вектор чисел с плавающей точкой:

void print(vector<double> v) // передача по значению; приемлемо ?

{

cout << "{ ";

for (int i = 0; i<v.size; ++i) {

cout << v[i];

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

}

cout << " }\n";

}

Функцию

print
можно применять к векторам любых размеров. Рассмотрим пример.

void f(int x)

{

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

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

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

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

print(vd1);

print(vd2);

print(vd3);

}

Этот код работает, но при первом вызове функции

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

Итак, нам необходим способ передачи функции

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

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

{

cout << "{ ";

for (int i = 0; i<v.size; ++i) {

cout << v[i];

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

  • Читать дальше
  • 1
  • ...
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: