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

Для улучшения производительности за счет уменьшения издержек на вызов функции вы можете заставить компилятор C++ встроить в программу код функции, подобно тому, как это делается при замещении макрокоманд.
Используя встроенные (inline) функции, ваши программы остаются удобными для чтения (читающий программу видит вызов функции), но вы избегаете издержек на вызов функции, которые вызваны помещением параметров в стек и их последующим извлечением из стека, а также переходом к телу функции и последующим возвратом из нее.
В зависимости от требований, предъявляемых к вашей программе, иногда вам потребуется использовать язык ассемблера для решения определенной задачи.
Для упрощения применения программирования на языке ассемблера C++ позволяет определить функции на встроенном языке ассемблера внутри ваших программ на C++.
ВСТРОЕННЫЕ ФУНКЦИИ

Когда вы определяете в своей программе функцию, компилятор C++ переводит код функции в машинный язык, сохраняя только одну копию инструкций функции внутри вашей программы. Каждый раз, когда ваша программа вызывает функцию, компилятор C++ помещает в программу специальные инструкции, которые заносят параметры функции в стек и затем выполняют переход к инструкциям этой функции. Когда операторы функции завершаются, выполнение программы продолжается с первого оператора, который следует за вызовом функции. Помещение аргументов в стек и переход в функцию и из нее вносит издержки, из-за которых ваша программа выполняется немного медленнее, чем если бы она размещала те же операторы прямо внутри программы при каждой ссылке на функцию. Например, предположим, что следующая программа CALLBEEP.CPP вызывает функцию show_message, которая указанное число раз выдает сигнал на динамик компьютера и затем выводит сообщение на дисплей:

#include <iostream.b>

void show_message(int count, char *message)


   int i; 
   for (i = 0; i < count; i++) cout << '\a'; 
   cout << message << endl; 
}

void main(void)


   show_message(3, "Учимся программировать на языке C++"); 
   show_mes sage(2, "Урок 35"); 
}

Следующая программа NO_CALL.CPP не вызывает функцию show_message. Вместо этого она помещает внутри себя те же операторы функции при каждой ссылке на функцию:

#include <iostream.h>

void main (void)


   int i; 
   for (i = 0; i < 3; i++) cout << '\a'; 
   cout << " Учимся программировать на языке C++" << endl; 
   for (i = 0; i < 2; i++) cout << '\a'; 
   cout << "Урок 35" << endl; 
}

Обе программы выполняют одно и то же. Поскольку программа NO_CALL не вызывает функцию show_message, она выполняется немного быстрее, чем программа CALLBEEP. В данном случае разницу во времени выполнения определить невозможно, но, если в обычной ситуации функция будет вызываться 1000 раз, вы, вероятно, заметите небольшое увеличение производительности. Однако программа NO_CALL более запутана, чем ее двойник CALL_BEEP, следовательно, более тяжела для восприятия.

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

Использование ключевого слова inline

При объявлении функции внутри программы C++ позволяет вам предварить имя функции ключевым словом inline. Если компилятор C++ встречает ключевое слово inline, он помещает в выполнимый файл (машинный язык) операторы этой функции в месте каждого ее вызова. Таким образом, можно улучшить читаемость ваших программ на C++, используя функции, и в то же время увеличить производительность, избегая издержек на вызов функций. Следующая программа INLINE.CPP определяет функции тах и min как inline:

#include <iostream.h>

inline int max(int a, int b)


   if (a > b) return(a); 
   else return(b) ; 
}

inline int min(int a, int b)


   if (a < b) return(a); 
   else return(b); 
}

void main(void)


   cout << "Минимум из 1001 и 2002 равен " << min(1001, 2002) << endl; 
   cout << "Максимум из 1001 и 2002 равен " << max(1001, 2002) << endl; 
}

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

О встроенных функциях

Если компилятор C++ перед определением функции встречает ключевое слово inline, он будет заменять обращения к этой функции (вызовы) на последовательность операторов, эквивалентную выполнению функции. Таким образом ваши программы улучшают производительность, избавляясь от издержек на вызов функции и в то же время выигрывая в стиле программы, благодаря использованию функций.

 

 

ВТОРОЙ ОТВЕТ 

 

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

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

Использовать ключевое слово inline легко, просто поставьте его перед именем функции. Затем, используйте её как обычную функцию.

Пример встроенной функции

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
 
using namespace std;
 
inline void hello()
{
  cout<<"hello";
}
int main()
{
  hello(); //Call it like a normal function...
  cin.get();
}

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

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

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

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