» » » » Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп

Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп

На нашем литературном портале можно бесплатно читать книгу Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп, Бьёрн Страуструп . Жанр: Программирование. Онлайн библиотека дает возможность прочитать весь текст и даже без регистрации и СМС подтверждения на нашем литературном портале litmir.org.
Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Название: Программирование. Принципы и практика использования C++ Исправленное издание
Дата добавления: 22 август 2024
Количество просмотров: 98
Читать онлайн

Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних просмотр данного контента СТРОГО ЗАПРЕЩЕН! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту readbookfedya@gmail.com для удаления материала

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

Программирование. Принципы и практика использования C++ Исправленное издание - читать бесплатно онлайн , автор Бьёрн Страуструп

Специальное издание самой читаемой и содержащей наиболее достоверные сведения книги по C++. Книга написана Бьярне Страуструпом — автором языка программирования C++ — и является каноническим изложением возможностей этого языка.
Помимо подробного описания собственно языка, на страницах книги вы найдете доказавшие свою эффективность подходы к решению разнообразных задач проектирования и программирования. Многочисленные примеры демонстрируют как хороший стиль программирования на С-совместимом ядре C++, так и современный -ориентированный подход к созданию программных продуктов. Третье издание бестселлера было существенно переработано автором. Результатом этой переработки стала большая доступность книги для новичков. В то же время, текст обогатился сведениями и методиками программирования, которые могут оказаться полезными даже для многоопытных специалистов по C++. Не обойдены вниманием и нововведения языка: стандартная библиотека шаблонов (STL), пространства имен (namespaces), механизм идентификации типов во время выполнения (RTTI), явные приведения типов (cast-операторы) и другие.
Настоящее специальное издание отличается от третьего добавлением двух новых приложений (посвященных локализации и безопасной обработке исключений средствами стандартной библиотеки), довольно многочисленными уточнениями в остальном тексте, а также исправлением множества опечаток.
Книга адресована программистам, использующим в своей повседневной работе C++. Она также будет полезна преподавателям, студентам и всем, кто хочет ознакомиться с описанием языка «из первых рук».

1 ... 86 87 88 89 90 ... 337 ВПЕРЕД
Перейти на страницу:
class="p1">double my_abs(int x) // предупреждение: этот код содержит ошибки

{

  if (x < 0)

    return –x;

  else if (x > 0)

    return x;

} // ошибка: если х равно нулю, функция ничего не возвращает

На самом деле компилятор может не заметить, что вы “забыли” про вариант x=0. Лишь некоторые компиляторы умеют это делать. Тем не менее, если функция сложна, компилятор может не разобраться, возвращает ли она значение или нет, так что следует быть осторожным. Это значит, что программист сам должен убедиться, что функция содержит инструкцию return или вызов функции error() как возможный вариант выхода.

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

В функции, не возвращающей никаких значений, инструкцию return можно использовать для выхода из нее, не указывая возвращаемую переменную. Рассмотрим пример.

void print_until_s(vector<string> v, string quit)

{

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

    if (v[i]==quit) return;

    cout << v[i] << 'n';

  }

}

Как видим, достичь последней точки функции, перед именем которой стоит ключевое слово void, вполне возможно. Это эквивалентно инструкции return;.

8.5.3. Передача параметров по значению

 

 Простейший способ передать аргумент функции заключается в пересылке копии его значения. Аргумент функции 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 << ", ";

  }

  cout << " }n";

}

Символ & означает ссылку, а ключевое слово const предотвращает случайную модификацию аргумента в функции print(). Кроме объявления аргумента, все остальное без изменений. Правда, теперь все операции будут производиться не над копией, а над самим аргументом, полученным по ссылке. Такие аргументы называются ссылками, потому что они ссылаются на объекты, определенные вне функции. Вызов функции 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(), какое-то значение, то компилятор сразу выдаст сообщение об этом.

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

{

  // ...

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

  // ...

}

Передача аргументов по константной ссылке — очень полезный

1 ... 86 87 88 89 90 ... 337 ВПЕРЕД
Перейти на страницу:
Комментариев (0)