Рекурсия

Из инструкций внутри функции разрешено вызывать эту же функцию. Такие вызовы называются рекурсивными.

Вернемся к примеру с вычислением чисел Фибоначчи. Следуя формуле расчета каждого числа как суммы двух предыдущих (за исключением двух первых, которые равны 1), легко написать рекурсивную функцию расчета чисел Фибоначчи.

int Fibo(const int n)
{
   if(n <= 1return 1;
   
   return Fibo(n - 1) + Fibo(n - 2);
}

В рекурсивной функции должен быть предусмотрен возврат управления без рекурсии, как в нашем случае внутри уловного оператора if для индексов 0 и 1. Иначе последовательность вызовов функции могла бы продолжаться бесконечно. На практике, поскольку незавершенные вызовы функции накапливаются в ограниченной области памяти под названием стек (см. раздел Инструкции объявления/определения, а также врезку "Куча"и "стек" в разделе Описание массивов), рано или поздно она закончится с ошибкой времени выполнения "Переполнения стека" ("Stack overflow"). Эта проблема продемонстрирована в функции FiboEndless.

int FiboEndless(const int n)
{
   return FiboEndless(n - 1) + FiboEndless(n - 2);
}

Обратите внимание, это не ошибка компиляции. Компилятор в данном случае не поможет даже предупреждением (хотя теоретически мог бы). Ошибка возникнет в процессе исполнения скрипта и будет выведена в журнал Экспертов в терминале.

Рекурсия может возникать не только при непосредственном вызове функции из неё самой. Например, если функция F вызывает функцию G, а та, в свою очередь, функцию F, то это тоже рекурсия, хоть и опосредованная. Таким образом, возможна рекурсия при цикличности вызовов любого порядка (глубины).