- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Шрифт:
Интервал:
Закладка:
Обратите внимание на то, что для константной ссылки l-значение не требуется. С ней можно выполнять преобразования точно так же, как при инициализации или при передаче по значению. При последнем вызове g(1,y,3) компилятор зарезервирует переменную типа int для аргумента cr функции g()
g(1,y,3); // означает: int __compiler_generated = 3;
// g(1,y,__compiler_generated)
Такой объект, создаваемый компилятором, называется временным объектом (temporary object).
Правило формулируется следующим образом.
1. Для передачи очень маленьких объектов следует использовать передачу аргументов по значению.
2. Для передачи больших объектов, которые нельзя изменять, следует использовать передачу аргументов по константной ссылке.
3. Следует возвращать результат, а не модифицированный объект, передаваемый по ссылке.
4. Передачу по ссылке следует использовать только в необходимых случаях.
Эти правила позволяют создавать очень простой, устойчивый к ошибкам и очень эффективный код. Под очень маленькими объектами подразумеваются одна или две переменных типа int, одна или две переменных типа double или соразмерные им объекты. Если вы видите аргумент, передаваемый по обычной ссылке, то должны предполагать существование функции, которая его модифицирует. Третье правило отражает ситуацию, в которой требуется функция, изменяющая значение переменной. Рассмотрим пример.
int incr1(int a) { return a+1; } // возвращает в качестве результата
// новое значение
void incr2(int& a) { ++a; } // модифицирует объект,
// передаваемый по ссылке
int x = 7;
x = incr1(x); // совершенно очевидно
incr2(x); // совершенно непонятно
Почему же мы все-таки используем передачу аргументов по ссылке? Иногда это оказывается важным в следующих ситуациях.
• Для манипуляций с контейнерами (например, векторами) и другими крупными объектами.
• Для функций, изменяющих сразу несколько объектов (в языке С++ функция может возвращать с помощью оператора return только одно значение).
Рассмотрим пример.
void larger(vector<int>& v1, vector<int>& v2)
// каждый элемент вектора v1 становится больше
// соответствующих элементов в векторах v1 и v2;
// аналогично, каждый элемент вектора v2 становится меньше
{
if (v1.size()!=v2.size() error("larger(): разные размеры");
for (int i=0; i<v1.size(); ++i)
if (v1[i]<v2[i])
swap(v1[i],v2[i]);
}
void f()
{
vector<int> vx;
vector<int> vy;
// считываем vx и vy из входного потока
larger(vx,vy);
// ...
}
Передача аргументов по ссылке — единственный разумный выбор для функции larger().
Обычно следует избегать функций, модифицирующих несколько объектов одновременно. Теоретически есть несколько альтернатив, например возвращение объекта класса, хранящего несколько значений. Однако есть множество программ, дошедших до нас из прошлого, в которых функции модифицируют один или несколько аргументов, и этот факт следует учитывать. Например, в языке Fortran — основном языке программирования, используемом для математических вычислений на протяжении более пятидесяти лет, — все аргументы передаются по ссылке. Многие программисты-вычислители копируют проекты, разработанные на языке Fortran, и вызывают функции, написанные на нем.
Такие программы часто используют передачу по ссылке или по константной ссылке. Если передача по ссылке используется только для того, чтобы избежать копирования, следует использовать константную ссылку. Следовательно, если мы видим аргумент, передаваемый по обычной ссылке, то это значит, что существует функция, изменяющая этот аргумент. Иначе говоря, если мы видим аргумент, передаваемый по ссылке, не являющейся константной, то должны прийти к выводу, что эта функция не только может, но и обязана модифицировать этот аргумент. Таким образом, мы обязаны тщательно проверить, действительно ли эта функция делает то, для чего предназначена.
8.5.7. Проверка аргументов и преобразование типов
Передача аргумента представляет собой инициализацию формального аргумента функции фактическим аргументом, указанным при ее вызове. Рассмотрим пример.
void f(T x);
f(y);
T x=y; // инициализация переменной x значением переменной y
// (см раздел 8.2.2)
Вызов f(y) является корректным, если инициализация T x=y; произошла и если обе переменные с именем x могут принимать одно и то же значение. Рассмотрим пример.
void f(double);
void g(int y)
{
f(y);
double x(y); // инициализируем переменную x значением
// переменной y (см. раздел 8.2.2)
}
Обратите внимание на то, что для инициализации переменной x значением переменной y необходимо преобразовать переменную типа int в переменную типа double. То же самое происходит при вызове функции f(). Значение типа double, полученное функцией f(), совпадает со значением, хранящимся в переменной x.
Преобразования часто оказываются полезными, но иногда преподносят сюрпризы (см. раздел 3.9.2). Следовательно, работая с преобразованиями, следует проявлять осторожность. Передача переменной типа double в качестве аргумента функции, ожидающей переменную типа int, редко можно оправдать.
void ff(int);
void gg(double x)
{
ff(x); // как понять, имеет ли это смысл?
}
Если вы действительно хотите усечь значение типа double до значения типа int, то сделайте это явно.
void ggg(double x)
{
int x1 = x; // усечение x
int x2 = int(x);
ff(x1);
ff(x2);
ff(x); // усечение x
ff(int(x));
}
Таким образом, следующий программист, просматривая этот код, сможет увидеть, что вы действительно думали об этой проблеме.
8.5.8. Реализация вызова функции
Как же на самом деле компилятор выполняет вызов функции? Функции expression(), term() и primary(), описанные в главах 6 и 7, прекрасно подходят для иллюстрации этой концепции за исключением одной детали: они не принимают никаких аргументов, поэтому на их примере невозможно объяснить механизм передачи параметров. Однако погодите! Они должны принимать некую входную информацию; если бы это было не так, то они не смогли бы делать ничего полезного. Они принимают неявный аргумент, используя объект ts класса Token_stream для получения входной информации; объект

