Встраиваемые функции
Одной из печальных истин программирования на языках, подобных С и С++, является то, что на вызов функций расходуется время. Хотя вызов функции происходит быстрее, чем вы успеете глазом моргнуть, многочисленные вызовы могут ухудшить общее быстродействие программы. Полный отказ от функций — неприемлемое решение этой проблемы! Функции делают программу модульной и более легкой для поддержки. Без функций исключительно сложно, может быть, невозможно написать даже среднюю по размерам корректно работающую программу. С другой стороны, разворачивание циклов и устранение многочисленных вызовов функций — стиль, сберегающий время и улучшающий общее быстродействие программы. Рассмотрим следующий гипотетический цикл 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 (демонстрация встраиваемых функций)
Для того чтобы объявить функцию встраиваемой, напишите перед ней ключевое слово 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 Все права принадлежат авторам размещенных материалов.
|