700_____________________________Часть II. Программирование на C++

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

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

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

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

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

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

inline void Swap( chars a, chars b); // объявление Swap

и в определении

inline void Swap( chars a, chars b) // определение Swap ( char t = a; a = b; b = t; }

присутствует ключевое слово inline. Встраиваемая функция, определяемая в классе, выглядит менее явно.