Информационный сайт

 

Реклама
bulletinsite.net -> Книги на сайте -> Программисту -> Мизрохи С.В. -> "Turbo Pascal и объектно-ориентированное программирование" -> 58

Turbo Pascal и объектно-ориентированное программирование - Мизрохи С.В.

Мизрохи С.В. Turbo Pascal и объектно-ориентированное программирование — М.: Финансы и статистика , 1992. — 192 c.
ISBN 5-279-00903-2
Скачать (прямая ссылка): efektispolzc2000.djvu
Предыдущая << 1 .. 52 53 54 55 56 57 < 58 > 59 60 61 62 63 64 .. 105 >> Следующая

Правило 33
131
'Томпите, как после каждого определения переменной в С вам советовали писать короткие комментарии, объясняющие, для чего она используется? Комбинируйте
одходящис названия переменных (см. правило 28) с понятными из контекста аргументами инициализации, и вы реализуете мечту любого программиста: у вас будст убедительная аргументация в пользу исключения отдельных комментариев.
Откладывая определение переменных, вы улучшаете эффективность программы, делаете ее более понятной и уменьшаете необходимость в документировании едгысла переменных. Похоже, пришла пора распрощаться с длинными списками определений переменных в начале блоков.
Правило 33. Тщательно обдумывайте использование встраиваемых функций
Встраиваемые функции... какая замечательная идея! Они выглядят подобно функциям, они работают подобно функциям, они намного лучше, чем макросы (см. правило 1). Их можно вызывать, не опасаясь накладных расходов функционального вызова. Чего еще желать?
В действительности вы получаете больше, чем рассчитывали, поскольку возможность избежать затраты функционального вызова - это только полдела. Оптимизация, выполняемая компилятором, обычно наиболее эффективна на участках кода, не содержащих вызовов функций. Таким образом вы даете компилятору возможность выполнять оптимизацию тела встраиваемой функции в зависимости от контекста, в который она попадает. При использовании «обычного» функционального вызова такая оптимизация была бы невозможна.
Все же давайте не будем слишком увлекаться. В программировании, как и в реальной жизни, не бывает «бесплатных завтраков», и встраиваемые функции здесь не исключение. Идея их использования состоит в замене каждого вызова такой функции ее телом. Не надо быть доктором математических наук, чтобы заметить, что это увеличит общий размер вашего объектного кода. Слишком частое применение встраиваемых функций на машинах с ограниченной памятью приводит к созданию программы, размер которой превосходит доступную память. Даже при наличии виртуальной памяти раздувание кода, вызванное применением встраиваемых функций, может привести к патологиям (пробуксовкам, thrashing) в механизме подкачки страниц, тормозящим выполнение программы. (Это, однако, отличная разминка для контроллера диска.) Злоупотребление встраиваемыми функциями может также уменьшить коэффициент попадания кэша команд процессора, что в свою очередь снизит скорость извлечения команд Из кэша в основную память.
С другой стороны, если тело функции очень короткое, код, генерируемый Для тела функции, может на самом деле быть короче кода, генерируемого для Бьізова функции. В таком случае встраивание функции может в действительности вести к уменьшению объектного кода и к более высокому коэффициенту попа-Дания кэша!
Следует иметь в виду, что директива inline, так же как и register, - это совет, а не команда компилятору. В результате всякий раз, когда компилятор сочтет
5*
Классы и функции: реализация
необходимым, он может игнорировать вашу директиву встраивания. И вынудить его к этому достаточно просто. Например, большинство компиляторов отказывается встраивать сложные функции (в частности, содержащие циклы или рекурсии), н, за исключением наиболее тривиальных случаев, вызов виртуальной функции отменяет встраивание. (В этом пет ничего удивительного: virtual значит «вызов конкретной функции определяется в момент выполнения», a inline - «в процессе компиляции замените вызов функции ее кодом». Если компилятор не «знает», какой вызов функции осуществлять, его трудно упрекнуть в том, что он отказывается делать встраивание функции.) Все это в конечном счете сводится к следующему: от реализации используемого компилятора зависит, встраивается ли в действительности встраиваемая функция. К счастью, большинство компиляторов обладает достаточными диагностическими возможностями и выдает предупреждения (см. правило 48) в том случае, если ие может выполнить заказанное вами встраивание.
Предположим, вы написали некоторую функцию f и объявили ее inline. Что получится, если компилятор по какой-либо причине решит отказаться от встраивания функции? Очевидный ответ заключается в том, что f не будет рассматриваться как встраиваемая функция: ее код сгенерируется так, как если бы это была нормальная (невстраиваемая) функция, а вызов f будет соответствовать обычному вызову функции.
Теоретически все должно произойти именно так, но мы рассматриваем как раз тот случай, когда практика может сильно отличаться от теории. Данная ситуация объясняется тем, что столь тонкое решение проблемы, связанной с не-встраиваемыми inline-функциями, было предложено в процессе стандартизации С++ относительно поздно. Более ранние спецификации языка (такие, как ARM - см. правило 50) предписывали компиляторам другое поведение, и «старорежимное» поведение все еще является достаточно распространенным, поэтому следует понимать, в чем оно заключается.
Немного подумав, вы обнаружите, что определения встраиваемых функций практически всегда размещаются в заголовочных файлах. Это позволяет включать одни и те же заголовочные файлы в несколько единиц трансляции (исходных файлов) для использования преимуществ, предоставляемых встраиваемыми функциями. Вот пример, в котором я придерживаюсь соглашения о том, что исходные файлы оканчиваются на . срр - это, наверное, наиболее распространенное в мире С++ соглашение об именах файлов:
Предыдущая << 1 .. 52 53 54 55 56 57 < 58 > 59 60 61 62 63 64 .. 105 >> Следующая
Реклама
Авторские права © 2009 AdsNet. Все права защищены.
Rambler's Top100