Здавалка
Главная | Обратная связь

Встраиваемые функции



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

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

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

Рассмотрим следующий гипотетический цикл for:

for (int i = 0; i < MAX; i++) { AnyFunction();

. . .

}

Если значение МАХ слишком велико, многократные вызовы AnyFunction() могут занять достаточно много драгоценного времени вдобавок к общему времени выполнения программы. Предположим, AnyFunction() на­писана следующим образом:

Void AnyFunction(void)

{

cout « AnyValue « '\n';

AnyValue++;

. . .

}

Все это, конечно, предположительно, но один факт не вызывает сомнений: вставка тела AnyFunction() не­посредственно в цикл for ускорит выполнение программы:

for (int i = 0; i <MAX; i++)

{cout << AnyValue << '\n'; AnyValue++;

. . .

}

Альтернативно можно объявить функции inline(встраиваемыми), вставляя тем самым их тела в поток кода. Как это сделать, показано в листинге 1.9.

Листинг 1.9. INLINE.CPP (демонстрация встраиваемых функций)

 


1: #include < iostream.h>
2:    
3: inline int max(int a, int b)
4: {  
5: if (a >= b)
6: return a;  
7: else  
8: return b;  
9: }  
10:    
11: main()  
12: {  
13: int x, y, z;
14:    
15: cout << " X? ";
16: cin >> x;  
17: cout << " Y? ";
18: cin >> y;  
19: z = max(x , y);
20: cout << " max(a, b) == " << z << '\n';
21: return 0;  
22: }  

Для того чтобы объявить функцию встраиваемой, напишите перед ней ключевое слово inline, как показано в строке 3. Пишется функция как обычно (строки 4-9). Ничего необычного в ее содержимом нет — все, что выполняется в любой функции, выполнится и для объявленной встраиваемой. Обычно встраиваемые функ-ции.подобные той, что определена в строках 3-9, объявляются в заголовочных файлах и включаются в каж­дый модуль, где необходимо их использование. Встраиваемую функцию необходимо полностью определить до того, как можно будет ее использовать, и включение ее текста в заголовочный файл — самый простой способ удовлетворения этого требования.

Используйте встраиваемые функции в точности так же, как вы используете обычные. Например, в строке 19 вызывается max() для определения большего из двух целых чисел с присвоением этого значения переменной z. Конечно, в скомпилированном коде Borland C++ не вызывает функцию max() в строке 19. Вместо этого компи­лятор вставляет тело функции непосредственно в программу, компилируя строку 19, как если бы она была напи­сана следующим образом:

if (x >= у)

z = x;

else z = у;

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

 

Встраиваемые функции сродни регистровым переменным. Когда вы объявляете встраиваемую функцию, вы лишь даете указание компилятору, и, если возможно, тело функции будет вставлено прямо туда, откуда эта функция вызывается. Разумеется, компилятор — не золотая рыбка, и нет гарантии, что так будет с каждой вашей командой. Если встраиваемый код, к примеру, слишком велик, то компилятор может отказаться вставить функцию в поток кода, и вместо этого сгенерирует обычный вызов. Также при компиляции программ для Turbo Debugger все встраиваемые функции будут преобразованы в обычные вызываемые функции, которые можно будет отлаживать. Хорошие программы на С++ работают корректно вне зависимости от того, как скомпилированы в них встраиваемые функции.


Управление памятью с помощью new и delete

Функ­ции malloc(), farmalloc(), farcalloc(), free(), farfree() и другие одинаково доступны для всех программ на С и С++.

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

Используйте new для выделения памяти динамическим переменным. Используйте free, чтобы освободить память, выделенную new, для ее использования в последующих операторах new.

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

Чтобы выделить память для переменной, имеющей тип double, и присвоить ее адрес указателю, вы можете написать

double *dp = new double;

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

double *dp = new(double);

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

Для присваивания значения содержимому памяти, адрес которой хранится в dp,

*dp = 3.14159;

Закончив использование динамической переменной, удалите ее следующим образом:

delete dp;

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

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







©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.