Встроенные функции (inline-функции)




встроенные функции с++, инлайн функции, inline функции, программирование для начинающихInline функции весьма занятный рудимент, доставшийся современному миру из уже далеких бандитских 90-х. Когда процветал ассемблер, Си компилировал очень компактные и маленькие программы, когда процессоры были слабенькими (по сравнению с тем, что сейчас в мобилки ставят к примеру) и время выполнения кода ценилось на вес золота. Этот тип функций вообще-то использовался не только в Си, и в то лихое время оправдывал себя.

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

Итак, что из себя представляет обычная функция? Возьмем например простой пример — вычисление факториала.

Достаточно простые вычисления факториала (5!) в цикле for, и возврат результата из функции. С++ расценивает эту функцию как некий блок операций, сгруппированный в отдельный блок. Блок этот после компиляции помещается в ячейки памяти единожды в коде, и тело функции (цикл в данном случае) нигде больше в скомпилированной программе не повторяется. Все красиво — получается некий участок памяти, принадлежавший программе, на который процессор при необходимости перескакивает с того места, где находит вызов.

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

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

Если описать наш факториал так:

То вместо

мы получим разворот функции в набор операторов:

как будто бы сами в коде написали в этом месте.

Соответственно код типа:

превратится в

Если мерить философски — количество кода с inline функцией увеличилось. Вместо одной строки вызова функции ее тело, подставленное вместо вызова , дало целых 6 строк. Так же будет и в скомпилированной программе — количество операторов возрастет многократно — на столько, сколько операторов в теле функции и сколько раз ее вписали в программу.

Т.е. различие между inline функцией и обычной функцией — дублирование кода тела функции везде, где она оказывается задействована. В обычной функции, её тело находится в единственном экземпляре в одном и том же месте внутри программы.

Где здесь выгода спросите вы? Экономится время процессора на прыжки с места вызова в тело функции. Если функция огромная и используется в нескольких местах, то inline получается не совсем выгодно. Однако, если функция (тело её) маленькое, с минимальным количеством операторов, решающих задачу, в старину было удобнее отказаться от прыжка и просто подставить их в нужное место, как будто сам программист там их описал.

Как бы там ни было, в бытовых условиях да еще и на современных компьютерах, программы, использующие inline подстановку тела функции вместо вызова, не дают особых преимуществ. Поэтому использовать этот вид функции приходится достаточно редко. ИМХО, ему место в музее славы. Хотя, чтоб быть до конца честным, такой подход дает свои плоды тем, кто программирует контроллеры, процессоры и прочие железяки. Но там свои особенности и свой подход, и в это углубляться сейчас не стоит. Использовать встроенную функцию (inline функцию) или нет — решать самому программисту. От себя могу добавить только одно — не стоит делать это там, где этого не требуется по заданию.




Рассылка новых уроков по программированию:


Согласен получать уведомления от purecodecpp.com на мой e-mail

Встроенные функции (inline-функции): 14 комментариев

  1. > Поэтому использовать этот вид функции приходится достаточно редко.

    Использовать inline функции явно приходится использовать, возможно, и не так часто. Но они массово используются неявно при определении классов и создании объектов:
    — любая функция-метод, определение котрой находится внутри определения её класса, неявно получает квалификатор inline.

    На примере класса, определяющего 2D-точку (на плоскости):

    И альтернативное 2-е определение, очень похожее:

    В 1-м варианте расстояние между 2-мя точками будет везде вычисляться inline, а во втором — вызовом функции-метода.

    1. Это уже забота компилятора. Имеется ввиду самому программисту редко приходится в бытовых условиях использовать этот вид функций.

      1. Нет. Это как раз тот случай, когда компилятору запрещено вмешиваться в реализацию метода: если метод описан внутри класса — inline, а если внутри метод только объявляе, а реализация либо вне объявления класса или в отдельном файле (что чаще) — функцимональный вызов.
        Это как-раз случай, когда реализация находится полностью под контролем автора, а автор должен знать чем его определения обернутся.

      2. Принцип инлайнов не меняется в зависимости от того, в ООП его применяют или в функционалке )
        К чему такие усложнения теории? Я не против уточнений, но тогда нужна еще одна статья, описывающая разницу между тем и этим случаями. Нет никакой надобности мешать всю теорию в кучу — получится тот же самый MSDN.

  2. ещё одной «мелочью» является то, что квалификатор inline является рекомендательным: компилятор использует его только если это возможно, если он считает, что это недопустимо, он использует функциональный вызов без всякого на то укедомленя (даже предупреждением).

    Пример — определите функцию факториала так:

    Здесь inline не сыграет никакой роли.

    1. Ну то же самое. В современном Си компилятор сам решает. В Си для 8086 или 80286 не все компиляторы так оптимизировали.

  3. Ещё одна «мелочь»: функции с квалификатором inline замечательно работают, но до тех пор, пока определение функции и вызов находятся в одном файле кода. При росте проекта, стоит разделить код на несколько файлов (раздельная компиляия с последующим связыванием объектных файлов), и это создаст огромные проблемы с поиском ошибки: inline функци не пригодны для внешнего связывания.

    inline — это определитель макроопределения, и они непригодны для внешнего связывания (линкования).

  4. > Этот тип функций вообще-то использовался не только в Си, и в то лихое время оправдывал себя.

    В стандарте языка C вообще нет ключевого слова inline, там подобные вещи реализуются через параметризированные макросы #define.
    В некоторых поздних компиляторах C inline включено, но только для пддержания совместимсоти с C++.
    Поэтому в принципе неверно говорить, что inline заимствовано из C, это — чисто C++ приобретение.
    Поэтому я бы вот то «залихватское» начало выбросил.

    1. А я не намекал на стандарт. Я намекал на ЯВУ. В Паскале тоже такие функции существовали. Да и в бейсике кажется было что-то подобное в поздних его видах.

      1. > Этот тип функций вообще-то использовался не только в Си

        В языке C не было ключевого слова inline от момента, когда его в 1969г. начал формулировать Денис Ритчи, и почти до 2000-х годов.
        Всё это время если слов inline появилось программе C, оно бы вызвало синтаксическую ошибку.

  5. К вопросу совместимости C и C++ … в отношении inline:

    Если компилировать код как C, но с ключом -std=c89 (т.е. стандарт ANSI 1989г.), то на inline просто будет синтаксическая ошибка. И на всех более ранних стандартах языка C.
    Использование inline в C допустит только компилятор с опцией -std=c99, т.е. такое ключевое слово допускается стандартом C только после 1999г.

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

    1. Я, когда ее писал, не желал вдаваться в особые подробности, чтоб не загораживать ими саму суть. Не зря в интернете есть правило «Многабукаф», которое зачастую раздувает контент в салат Ой-Ливьйо.

Добавить комментарий

Код размещайте в тегах: <pre class="lang:c++ decode:true ">YOUR CODE</pre>