Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Штерн В. - Основы C++. Методы программной инженерии - 2003

.pdf
Скачиваний:
267
Добавлен:
13.08.2013
Размер:
28.32 Mб
Скачать

840Часть IV • Расширенное использование С'^-ь

Для использования символьных строк и динамического управления памятью

Для применения имеющихся библиотек (стандартов де-факто)

C++ как традиционный язык программирования

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

Встроенные типы данных C+ +

Целый тип является самым быстрым типом на любой платформе. Размер его составляет 16 бит на 16-битовой машине и 32 бита на 32-битовых машинах. Та­ ким образом, вы можете столкнуться с проблемами переносимости, типичными для C+ + . Нет гарантии, что программа, которая выполняется на одной машине, даст подобные результаты на другой машине.

С целью повышения гибкости (т. е. для сохранения памяти) и добавления вы­ числительных возможностей (т. е. для расширения диапазонов, когда необходимо) для сложных вычислений C + + предусматривает модификаторы размера (short, long, unsigned) для более тонкого использования памяти. В C + + не стандартизо­ ваны размеры различных типов. Он требует, чтобы короткое значение не было длиннее целого значения, а также, чтобы длинное значение не было короче целого значения.

На современных машинах короткие значения всегда занимают 16 бит, а длин­ ные значения — 32 бита. Программисты, которые стремятся к переносимости, избегают явного использования целых значений и вместо них используют либо короткие, либо длинные модификаторы. Программисты, которые стремятся к ско­ рости, используют простые целые и избегают использования коротких и д/шнных модификаторов.

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

Для упроидения программистам выбора C + + поддерживает значения по умол­ чанию. Если программист не укажет, со знаком число или без знака, то по умол­ чанию считается, что знак есть. Если программист не определит, является ли значение коротким целым, длинным целым или просто целым, значение по умол­ чанию представляет собой целое значение.

Поскольку вы стремитесь повысить производительность, C + + не проверяет результаты вычислений ни на потерю значимости, ни на переполнение. Все, что следует проверить в программе, должно быть изучено явно в Ее исходном тексте в определенное время. Если программа не желает тратить время на проверку допустимости результата, то в C + + не предусматривается каких-либо тестов по умолчанию или предупреждений.

Глава 19 • Полученные уроки

84 i

Символы в С+Н- интерпретируются как особый вид целых значений. Их размер изменяется от одного байта на символ до двух байтов на символ (расширенный набор символов). Арифметические операции над символьными значениями допус­ тимы в C+ + . Они широко используются, но могут создавать проблемы с перено­ симостью, когда различные машины применяют разные наборы символов.

Язык позволяет программисту определить как символы со знаком, так и без знака. Для типа по умолчанию стандарт отсутствует. На некоторых машинах при­ меняются символы без знака, на других — со знаком. Предположите, что символ не может содержать отрицательное значение и использовать вместо символа целое, если допускаются отрицательные значения (например, код конца файла (end-of-file)).

Символьные литералы заключаются в одиночные кавычки. Не путайте их со строковыми литералами, заключаемыми в двойные кавычки. C + + не сохраняет длину строки в содержимом строки. Для указания конца строки используется код 0. Именно поэтому длина строкового литерала на единицу больше, чем коли­ чество символов в литерале.

Для типов с плаваюш^ей точкой C + + поддерживает три размера: float, double и long double. Их размер может быть 4, 8 и 10 байт, точности в диапазоне 7, 15 и 19 цифр. Характеристики эти зависят от машины. Константы в C++, с плаваю- ш,ей точкой всегда double, не float и не long double. В большинстве случаев это не важно. Когда необходимо объявить, что литерал, например, типа float, вос­ пользуйтесь соответствуюи;им суффиксом. C + + поддерживает как запись с фик­ сированной десятичной точкой, так и экспоненциальное представление чисел.

Логические типы имеют два значения: true и false. Они также представляются как малые целые. Размер логического значения типа bool один байт, а не один бит. C + + не упаковывает логические значения в один бит, поскольку для адресации отдельных битов в C + + требуются логические операции и сдвиги. При выборе компромисса между эффективностью использования памяти и эффективными затратами времени в C + + предпочтение отдается эффективности по времени, поскольку байт является наименьшей долей памяти, которую можно непосред­ ственно адресовать.

Символические имена для значений литералов любых встроенных типов могут определяться с помош^ью директивы препроцессора #define. Препроцессор заме­ нит каждое появление символического имени в исходной программе на литераль­ ное значение. Поскольку эта процедура выполняется до того, как компилятор увидит исходный текст программы, часто ошибки в директивах препроцессора очень трудно отыскать. Лучше использовать модификатор const, потому что имена, определенные в модификаторе const, соответствуют правилам области действия (имена, заданные в директиве #def ine, являются глобальными).

Для каждого типа данных C + + поддерживает два производных типа данных: тип указателя и тип ссылки. Они содержат адрес значения, но синтаксис их отли­ чается.

C + + допускает любые преобразования между числовыми значениями разных типов: значение одного типа может использоваться, когда ожидается значение другого типа. Логические значения и числовые значения также взаимозаменяе­ мы — синтаксическая ошибка не выдается. Для числовых значений C + + являет­ ся языком со слабым контролем типов.

Значения указателей (или ссылок) на разные типы невозможно преобразовать друг в друга. Для адресов C + + является языком со строгим контролем типов. Синтаксическая ошибка генерируется, когда указатели разных типов содержат одинаковый адрес.

Для преобразований указателей (и ссылок) может использоваться явное при­ ведение типа, но за целостность результатов отвечает сам программист. Компи­ лятор не выдает никаких синтаксических ошибок, если результаты не имеют разумного значения или не переносимы на компьютеры с другой архитектурой.

842 Часть IV • Расширенное использование С4»4«

Выражения С+ +

Язык C + + включает следуюидие операции над числовыми значениями: опера­ ции со знаком, арифметические операции, операции отношений, операции равен­ ства и логические операции. Отсутствует операция возведения в степень. Подобно большинству других языков программирования, он не содержит неявного умноже­ ния — в качестве явного оператора должен использоваться символ "звездочка".

C + + интерпретирует операции как выражения. Для достижения единообразия C + + интерпретирует присвоение и запятую как операции (хотя у них самый низ­ кий приоритет). В результате ошибочные структуры могут быть приняты компиля­ тором C + + как допустимый код.

Поскольку количество операций большое, в C + + используются двухсимвольные и даже одна трехсимвольная операция (знак операции вычисления выражения по условию). В C + + значение операции (и зарезервированного слова) часто по­ вторно используется для различных целей и поэтому определяется с помош,ью контекста.

Поскольку размер встроенных типов данных зависит от машины, C++ позво­ ляет программисту оценивать размер указанной переменной (указывая имя пере­ менной) или размер любой переменной указанного типа (обозначая наименование типа). Логические операции, операции отношений и равенства возвраш,ают буле­ вы значения: true и false, но они могут свободно преобразовываться в числовые значения 1 (true) и О (false). Кроме того, когда ожидается булево значение, мо­ жет использоваться любое числовое значение — синтаксическая ошибка не выда­ ется. Значение О преобразуется в false, а любое другое значение интерпретируется как true. В этом случае компиляторы C + + иногда вынуждены принимать код, который является семантически неверным.

Другим источником ошибок является операция равенства, которая записыва­ ется как два последовательных знака равенства: отсутствие одного знака равен­ ства не вызывает выдачу синтаксической ошибки, но коренным образом меняет смысл исходного текста программы.

Логические операции && и | | имеют разный приоритет — операция && связы­ вает более тесно, чем | |. Это позволяет избегать дополнительных скобок. Обе логические операции являются операциями ближнего действия. В составных логи­ ческих выражениях оценивается первый операнд. Если результат операции из­ вестен из оценки первого оператора, то второй операнд не оценивается.

В C + + имеется множество уникальных операций, которые обеспечивают доступ к базовым представлениям информации в компьютерной памяти. Это по­ битовые логические операции, среди которых "включаюш,ее или", "исключаюш^ее или", "отрицание" (дополнение). Они обрабатывают каждый бит операнда по отдельности.

Побитовые сдвиги осуи;ествляют сдвиг указанного набора битов влево или вправо. Когда набор сдвигается влево или положительное число сдвигается впра­ во, освободившиеся места дополняются нулями — эти операции являются пере­ носимыми. Если отрицательное число сдвигается влево, результат зависит от реализации: освободившиеся места заполняются либо нулями (логический сдвиг), либо единицами (арифметический сдвиг). Названные операции не являются пере­ носимыми.

Другой набор уникальных операций включает операции инкремента и декре­ мента. Они эмулируют обработку, подобную языку ассемблера, создавая побоч­ ный эффект (увеличение или уменьшение на 1) для одного операнда единичного значения. Эти операторы могут быть префиксными или постфиксными. Префикс­ ный оператор применяется первым, затем значение используется в остальных выражениях. Постфиксный оператор применяется после того, как значение ис­ пользуется в других выражениях.

В выражении.в C + + определяется порядок оценки операторов. Однако он не обозначает порядок оценки операндов. Следовательно, в программе на C+ +

Глава 19 • Полученные уроки

843

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

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

Другой набор уникальных операций C+-I- включает оператор арифметического присваивания и оператор-запятую. Эти операции помогают в написании лаконич­ ной и выразительной программы на C++ .

Бинарные операции C + + всегда применяются к операндам одинакового типа. Когда в исходной программе определяются операнды разных типов, C + + исполь­ зует преобразования расширения. Операнд меньшего размера преобразуется к типу выражения с самым большим размером. В операторе присваивания значе­ ние, расположенное справа, преобразуется к типу значения слева.

Управляющая логика в C+ +

Как и в других языках, операторы C + + выполняются последовательно. Каж­ дый оператор завершается точкой с запятой. Допускаются блоки (составные опе­ раторы). Они заключаются в скобки и могут содержать локальные переменные. После закрываюш^ей скобки блока точка с запятой не указывается.

Составные операторы могут быть вложены, они являются телом функции или телом оператора управления. Область видимости локальных переменных, опреде­ ленных во вложенном блоке, обозначается рамками блока.

C + + содержит стандартный набор управляюш,их структур. В операторе if-else не используется зарезервированное слово then. Когда результатом выражения оператора является значение любого типа, не равное нулю, выполняется ветвь true, а когда результат равен нулю (false), применяется ветвь false.

C + + реализует выполнение повторяюндихся действий и поддерживает три формы операторов организации циклов: цикл while (допускает повторение до нуля), цикл do-while (выполняется хотя бы один раз) и цикл for (используется для фиксированного количества повторений).

Популярный стиль программирования на C + + состоит в объединении провер­ ки непрерывного цикла с присваиванием. Будьте осторожны со скобками. Пропу- ш,енные скобки могут изменить смысл выражения, поскольку операция сравнения

в C + +

имеет более высокий приоритет, чем операция присваивания.

C + +

не поддерживает неограниченные переходы. Оператор goto не может

выйти за пределы своей области видимости и осуш,ествить переход через опреде­ ления переменных. Оператор break выполняет выход из цикла таким образом, что управление передается оператору, расположенному за циклом. Оператор break может использоваться во всех трех структурах организации циклов и обычно вы­ полняется в условных операторах. Оператор continue пропускает оставшуюся часть тела цикла и возвраш,ается к началу цикла для проверки условия последую- ш,их итераций.

Оператор выбора (switch) в языке C + + поддерживает в программе решение для множественного ветвления. Он обеспечивает переход на альтернативные вет­ ви выполнения в зависимости от значения целочисленного выражения. (Нельзя использовать значения с плаваюш^ей точкой.) Ветвь по умолчанию выполняется, если не находится совпадение. В отличие от других языков оператор по умолчанию не является обязательным. Если он отсутствует и не найдено совпадение, задается следуюш,ий оператор. Для создания структур с несколькими ветвями операторы break должны использоваться в конце каждый ветви.

г

844

Часть iV • Расширенное использование C+^

 

C++ как модульный язык

C + + поддерживает иерархии компоновочных блоков для данных и для опера­ ций программы. С точки зрения программной инженерии, к преимуидествам раз­ биения больших проектов на модули относится разделение труда, упрощение задач программирования, повторно используемые и сопровождаемые программные ком­ поненты и возможность изучения программы на разных уровнях: либо в общем плане (независимо от деталей), либо подробно (не учитывая вопросы высокого уровня).

За счет корректного использования подобных преимуществ повышается про­ изводительность как при разработке, так и при сопровождении программ. Кроме того, сокращается количество ошибок.

C + + поддерживает составные типы данных, определяемые программистами: массивы, структуры, объединения и перечисления. Их компоненты могут быть либо встроенных типов данных, либо других составных типов C + + (массивы, структуры и т. п.).

C + + поддерживает функции, определенные программистом. Иерархия функ­ ций повторяет иерархию действий реа/1ьных объектов, информация о которых сохраняется в программе. C + + использует стандартные библиотеки, которые обеспечивают выполнение большого количества разнообразных задач общего назначения. Библиотечные функции оптимизированы, хорошо протестированы и широко применимы.

Составные типы C+ + : массивы

Массивы C + + могут содержать элементы только одного типа. Самым боль­ шим ограничением массивов C + + является требование, что на момент выполне­ ния компиляции размер массива должен быть известен. Если массив содержит больше элементов, чем необходимо, то напрасно расходуется память. Если массив включает меньше положенного количества элементов, то искажается информация в памяти.

Еще одним обычным источником ошибок при использовании массивов C+ + является то, что индекс первого элемента всегда равен нулю. Изменить это невоз­ можно. Следовательно, индекс последнего элемента всегда на единицу меньше диапазона массива. В C + + не поддерживается проверка индекса во время выпол­ нения. Компилятор не будет это делать ни при каких обстоятельствах. C + + также не поддерживает проверку допустимости индекса во время выполнения.

Имейте в виду, что нежелательно расходовать напрасно время при любом об­ ращении к массиву. Если требуется проверить допустимость значения индекса, можно написать собственную программу. Когда проверка допустимости индекса не выполняется, C + + предполагает, что так и надо. На машинах с большой памятью ошибки индекса могут не приводить к неверным результатам. Это серьезная проб­ лема, которую трудно предотвратить и решить.

C + + позволяет программисту реализовать алгоритмы обработки массивов, используя для доступа к элементам массива либо индексы, либо указатели. Это основано на том факте, что при применении операции инкремента (или декремен­ та) к указателю осуществляется приращение адреса не на единицу, а на длину эле­ мента массива. Такая операция устанавливает указатель на следующий элемент массива. Использование указателей позволяет писать краткие и выразительные программы обработки массивов. Однако при использовании этого метода отсутст­ вуют преимущества в плане производительности. Некоторые программисты пола­ гают, что программы такого вида довольно трудно проверить.

C + + поддерживает массивы любой размерности. Они реализуются как одно­ мерные массивы с развертыванием их по строкам. (Правый индекс изменяется быстрее остальных.) Одномерные и многомерные массивы C + + не поддерживают проверку допустимости индекса.

Глава 19 • Подученные уроки

845

Текст в C + + представляется как массив символов. Эти массивы

должны

включать дополнительный элемент для размещения нулевого разделяющего зна­

чения, которое используется в качестве метки конца допустимых данных в масси­ ве. Когда компилятор обрабатывает литеральные константы текста программы, он также добавляет завершающий нуль к символам строки. Следовательно, литералы содержат дополнительный элемент. Все библиотечные функции, обрабатывающие массивы символов, предполагают наличие завершающего нуля в конце допусти­ мых данных. Когда библиотечные функции изменяют содержание массива, они добавляют завершающий нуль к концу допустимых данных, чтобы сохранить достоверное состояние строки.

С + + не поддерживает ни присваивания, ни сравнения массивов. Для масси­ вов произвольных типов именно программист отвечает за правильность выпол­ нения этих операций. Для строк текста библиотечные функции используются для выполнения присваивания, сравнений, сцеплений и других стандартных операций.

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

Составные типы C+ + :

структуры, объединения, перечисления

Структуры C + + объединяют связанные компоненты. Программист решает, какие компоненты являются связанными, а какие нет.

Определение структуры является основой создания переменных типа структу­ ры. Для каждого поля структуры программист указывает тип и имя поля. Область действия определения структуры ограничивается открывающей и закрывающей фигурной скобкой с последующей точкой с запятой.

Переменные типа структуры могут инициализироваться с помощью синтакси­ са, сходного с синтаксисом инициализации массива.

Операция селектор-точка выбирает поля объектов структуры (как 1-значение, так и г-значение). Когда указатель ссылается на переменную типа структуры, опе­ рация селектор-точка не работает. Вместо него должна использоваться операция селектор - стрелка.

C + + поддерживает присваивание переменных одного типа для структуры. Реализованы семантики значений: поля г-значения переменной типа структуры копируются побитно в поля 1-значения переменных типа структуры.

Присваивание для переменных типа структуры с различным типом не разреша­ ется, даже когда они одинакового состава и когда поля в определениях структур имеют одинаковые имена. Должно быть одинаковое имя типа. Обратите внимание на то, что использование возможности typedef не обеспечит одинаковое имя типа. Она только синоним для имени типа.

Также не допускаются присваивания между переменными типа структуры и числовыми переменными (или переменными указателями или ссылками). В от­ ношении типов, определенных программистом, C + + является языком со строгим контролем типа. Такие присваивания помечаются компилятором как синтаксиче­ ские ошибки.

C + + не поддерживает проведение различных операций в отношении структур. Реализовать операции со структурами можно в своих собственных программах.

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

I 846 I

Часть IV • Расширенное использование C^-i^

Такая схема позволяет программе сохранить пространство в памяти. Перемен­ ная типа union может содержать информацию одного из взаимоисключающих типов, указанных в определении типа union. Это способствует появлению ошибок, поскольку программист должен убедиться, что значение, извлеченное из перемен­ ной типа union, и значение, сохраненное ранее в этой переменной, совпадают, а само объединение не располагает средствами для сохранения информации о типе.

Если программа делает ошибку и извлекает значение другого типа, то сообще­ ние об ошибке не выдается ни во время компиляции, ни во время выполнения. Бесполезный набор битов извлекается без каких-либо сообщений. Чтобы избе­ жать подобных ошибок, переменные типа union могут использоваться как поля структур. К структуре можно добавить поле признака для сохранения информации о том, как было инициализировано значение поля union. Когда извлекается зна­ чение union, команда обращается к полю признака и действует соответствующим образом. Так обычно реализовывался полиморфизм, прежде чем были изобрете­ ны виртуальные функции.

Перечислимые типы определяют переменные, которые принимают значения из предварительно определенного набора символьных идентификаторов. Синтак­ сис определения перечислимого типа подобен синтаксису определения структуры. Набор символьных имен, разделенных запятыми, указывается в фигурных скобках (с последующей точкой с запятой). Это общераспространенный способ определе­ ния символьных констант в программе.

C + + не определяет операции над значениями перечислимого типа. Они реа­ лизуются как целое. Программа может использовать эту информацию, но мы не советуем это делать.

Функции С+ + как средства обеспечения модульности

C + + позволяет скрыть внутреннюю сложность функционирования. Клиент­ ская программа использует серверные функции как отдельные блоки программы. Это позволяет упростить код вызывающей программы в соответствии с ее на­ значением. Клиентская программа представляется функцией, вызывающей сер­ верные функции, а не как последовательность деталей более низкого уровня из операций над данными.

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

Функции C + + работают совместно друг с другом над достижением общей цели программы. Они обрабатывают общие данные. Значения данных могут уста­ навливаться одной функцией, а использоваться другой функцией. Обмен данными реализуется за счет использования глобальных переменных, параметров и воз­ вращаемых значений. Связывание посредством глобальных переменных является неявным. Оно не сразу очевидно программисту, осуществляющему сопровожде­ ние, и, следовательно, должно использоваться как можно реже.

Связывание посредством параметров лучше, поскольку оно явное. Програм­ мисту, осуществляющему сопровождение (и программисту клиентской части), сразу же становится ясно, какие значения вовлекаются в поток данных между функцией и ее клиентскими функциями.

Связывание (количество параметров) должно уменьшаться до минимума по­ средством разделения обязанностей между функциями. Однако то, что составля­ ет единое целое, не должно быть разделено между различными функциями. При разделении одного целого на части необходимо обменяться данными между функциями.

Глава 19 • Полученные уроки

847

С помощью функции клиентская программа должна передать фактический параметр для каждого формального параметра в определении функции. Можно определить значения по умолчанию д/1я параметров, чтобы они использовались, когда клиентская программа не обозначает значения фактических параметров.

В отношении передачи параметра C + + спроектирован как язык со строгим контролем типов. Количество аргументов должно совпадать с числом формальных параметров, а тип каждого аргумента с типом соответствующего формального параметра. Случаи, когда вы не придерживаетесь данного правила, помечаются компилятором как синтаксические ошибки.

Исключение из этого правила делается только для числовых типов. Если типы формального параметра и соответствующего фактического аргумента не совпа­ дают, могут применяться преобразования типов. Малые аргументы (enum, char, unsigned char, short) повышаются до целых, короткие без знака становятся либо int, либо int без знака (в зависимости от архитектуры машины), а аргументы с плавающей точкой повышаются до типа double. Если после повышения тип фактического аргумента все еще не совпадает с типом формального параметра, то применяется преобразование. Любой числовой тип можно перевести в любой другой числовой тип, даже если это приводит к потере точности (например, из double в integer).

Повышения и преобразования не применяются к типам, определенным про­ граммистом, указателям и ссылкам. Они используются только для числовых

типов.

 

С+Н

язык с раздельной компиляцией. Для облегчения работы компилятора

перед обработкой вызова функции компилятор должен знать ее интерфейс. Не­ смотря на то, что определение функции предшествует в исходном файле вызову функции, должен использоваться прототип с указанными типами параметров и возвращенного значения. Имена параметров в прототипе функции полезны, но не обязательны.

Функция C + + может определяться только один раз. Она может быть объяв­ лена как прототип неоднократно. Если функция используется в нескольких фай­ лах, она должна быть объявлена в каждом из них. Прототипы функций часто помещаются в заголовочные файлы #include.

Глобальная функция C + + определяется ее именем и последовательностью типов ее параметров. Когда функция огфеделяется как член класса, имя класса также является частью определения функции. Эта комбинация (сигнатура функ­ ции) — имя класса (если имеется), имя функции и список типов параметров — должна быть уникальной. Следовательно, имя функции может быть перегружено. Функция с тем же именем, но с другим набором параметров, будет рассматри­ ваться как другая функция. Возвращаемый тип не является частью сигнатуры функции.

Функция C + + может определяться как строковая функция. Вместо вызова функции компилятор генерирует для нее объектную программу и вставляет ее в клиентскую программу. Когда вызывается эта функция, не тратится время на контекстный переключатель. Для приложений, которые беспокоятся за скорость выполнения, это важно.

В C + + имеются только функции. Процедуры отсутствуют. Если для приложе­ ния требуется процедура, используйте функцию void.

Если функция возвращает значение, то C + + позволяет вызывающей програм­ ме игнорировать возвращаемое значение в вызове и использовать функцию как оператор. Многие библиотечные функции C + + содержат редко используемые возвращаемые значения. Однако игнорирование возвращаемых значений не явля­ ется хорошей практикой.

848 Чость IV • Расширенное использование С-^'^

Функции C+ + : передача параметров

в C + + параметры передаются по значению. В момент вызова в стеке выделя­ ется память и локальные переменные, а значения аргументов (переменные, выра­ жения или литералы) копируются в область памяти, выделенную для параметров. Эти значения используют функции. Когда выполнение функции завершается, вы­ деленная память возврапдается в стек.

При передаче параметров фактические аргументы передаются формальным параметрам. Измененные значения параметров обратно не передаются и факти­ ческие аргументы в области видимости клиента не изменяются.

Для побочных эффектов в клиентской программе C + + поддерживает передачу по указателю: вместо значения указанного типа как фактического аргумента пере­ дается указатель на значение. Указатели C + + являются переменными. Значение указателя копируется в формальный параметр. Когда указатель используется во время выполнения функции, он содержит адрес переменой в клиентском про­ странстве. Значение этой переменной при необходимости может изменяться через указатель.

Когда выполнение функции достигает закрывающей фигурной скобки, указа­ тель вместе с другими формальными параметрами уничтожается. Следовательно, функция не может изменять значение указателя. Но это не проблема, поскольку изменять адрес нет необходимости. Цель передачи параметра по указателю — изменение переменной в клиентском пространстве, адрес которой передается как фактический параметр.

Передача параметров по указателю — сложный процесс. Программист дол­ жен скоординировать программу в трех точках:

1)запись указателя (*), которая используется в заголовке функции и в прототипе;

2)оператор разыменования (*), который применяется в теле функции;

3)адрес оператора (&), который используется при вызове функции.

Для упрощения передачи параметра C + + добавляет еще один режим передачи параметра, который поддерживает побочные эффекты в пространстве вызываю­ щей программы. При передаче по ссылке координация различных точек в про­ странстве проще:

1)имя переменной с операторами, которое используется в заголовке функции,

2) операция ссылки (&), которая применяется в теле функции,

3)имя переменной без операторов, которая используется в вызове функции.

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

Массивы в C + + передаются таким же образом независимо от того, изменяют­ ся ли его компоненты в теле функции или нет. Программу необходимо скоордини­ ровать в следующих трех направлениях:

1)имя массива с пустыми круглыми скобками в заголовке функции,

2)запись индекса (или имени массива без круглых скобок) в теле функции,

3)массива без круглых скобок в вызове функции.

Объекты структур C + + могут передаваться по значению, по указателю и по ссылке. По значению параметры передаются так: имя переменной без модифика­ торов используется во всех трех местах (в заголовке функции, в теле функции

Глава 19 • Полученные уроки

и в вызове функции). Однако в нем не поддерживаются побочные эффекты в клиентском пространстве. Даже когда они не требуются, передача по значению может быть нежелательной при отправлении больших структур переменных. Копирование их может замедлить работу программы. Передача параметров по указателю сложна, но она поддерживает побочные эффекты в клиентском про­ странстве и в ней не требуется копирование данных даже для больших структур. Передача параметров структур по ссылке учитывает преимуш^ества передачи по значению и передачи по указателю.

Такой режим передачи параметров используется как для ввода, так и для вы­ вода параметров с типами, определенным^ пользователем. Чтобы сообщить программисту, осуш^ествляющему сопровождение, какие параметры изменены функцией, а какие нет, проектировш,ик использует модификатор const для входных параметров, не модифицированных функцией. С помош,ью данного метода выра­ жается явное намерение проектировш^ика в программе, а не в комментариях.

Область видимости и класс памяти в C+ +

Лексический контекст в С4-+ обычный. Объекты (переменные) определяются в начале (или в середине) области видимости, обозначенной фигурными скобками. Имена, определенные в области видимости, могут повторно использоваться в не­ зависимых областях видимости. Если имя повторно используется во вложенных областях видимости, то объект во внутренней области видимости скрывает объект во внешней области видимости.

Класс памяти (экстент) является промежутком во время выполнения, когда для объекта выделяется память, а его имя связывается с ячейкой памяти. Большин­ ство переменных C + + принадлежат автоматическому классу памяти. Это те пере­ менные, которые определяются локальными переменными в области видимости функции или блока. Память для автоматической переменной выделяется из сис­ темного стека, когда выполнение достигает открываюш,ей фигурной скобки блока.

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

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

Преимупдество использования автоматических переменных состоит в том, что имя может повторно использоваться в различных функциях без какой-либо коор­ динации действий между разработчиками.

Глобальные (или внешние) переменные объявляются вне любой функции, в начале файла либо где-то в его границах. Область их действия распространяется от места объявления до конца файла. Память для глобальных переменных выделя­ ется до начала выполнения программы (открываюи;ая фигурная скобка в main) и возвраш,ается, когда выполнение достигает закрывающей фигурной скобкита1п.

Глобальные переменные могут инициализироваться при объявлении. Если глобальная переменная не инициализирована, то по умолчанию ей присваивается исходное значение, равное нулю.

Глобальная переменная может быть повторно объявлена как локальная пере­ менная в любом файле или в функции. Локальное имя скрывает глобальное имя в области действия блока, в котором определено локальное имя. Локальное имя использует другую область памяти и не оказывает влияния на память, выделенную для глобальной переменной.

Соседние файлы в предмете Программирование на C++