Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
A.doc
Скачиваний:
36
Добавлен:
09.04.2015
Размер:
5.6 Mб
Скачать

236 Глава 5

Поддержка отрицательных степеней проста; здесь просто используется тот факт, что х" может быть вычислено как (1/х)n. Поэтому если n отрицательно, то х присва- ивается 1.0/х, а знак п меняется на положительный.

В следующем операторе i f принимается решение о том, должна ли функция power () вызывать саму себя еще раз:

В случае если п равно нулю, функция возвращает 1. О, в других случаях возвра- щает результат вычисления выражения x*power (х, п-1), то есть функция power () вызывается еще раз с показателем степени, на 1 меньше. Таким образом, ветвь else оператора if обеспечивает механизм, необходимый для прерывания бесконечной по- следовательности рекурсивных вызовов функции.

Понятно, что если внутри функции power () значение п больше нуля, то выпол- няется следующий вызов power (). Фактически для любого заданного значения п, отличного от 0, функция вызывается п раз, независимо от знака п. Этот механизм проиллюстрирован на рис. 5.4, где предполагается, что аргумент — показатель степе- ни — равен 3.

Как видите, функция power () вызывается четыре раза, чтобы сгенерировать х3, из которых три вызова рекурсивны, то есть, функция три раза вызывает саму себя.

Использование рекурсии

Если только вы не имеете дело с проблемой, которая сама по себе диктует не- обходимость использования рекурсивных функций, или существуют очевидные аль- тернативы, то лучше применить другой подход, например, цикл. Это намного более эффективно, чем рекурсивные вызовы функций. Подумайте о том, что происходит в последнем примере, когда нужно вычислить простое произведение х*х*. . . х, причем п раз. При каждом вызове компилятор генерирует копии двух аргументов функции и отслеживает место в памяти, куда нужно вернуть значение, при каждом выполнении return. Кроме того, ему необходимо сохранить содержимое различных регистров компьютера, чтобы они использовались внутри функции power (), и конечно, восста- навливать их значение при каждом возврате. При сравнительно небольшой глубине рекурсивных вызовов накладные расходы будут заметно больше, чем при использова- нии цикла.

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

Структурная организация программ 237

Программирование на C++/CLI

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

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

  • Когда параметром является массив, нет необходимости в дополнительном па- раметре, передающем его длину, поскольку массивы C++/CLI хранят в себе ин- формацию о собственной длине — в свойстве Length.

  • Нельзя применять адресную арифметику с параметрами-массивами в програм- мах C++/CLI, как это делается в программах на родном С++, то есть всегда нуж- но использовать индексацию массивов.