递归

允许从函数内部的语句调用同一个函数。这种调用称为递归调用。

我们回到计算斐波那契数的例子。根据将每个数计算为前两个数之和的公式(前两个数除外,它们都等于 1),就很容易写出计算斐波那契数的递归函数。

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

递归函数必须能够在递归结束的情况下返回控制权,类似我们在条件语句 if 中索引 0 和 1 的情况。否则,函数调用序列可能会无限期地继续下去。实际上,因为未完成的函数调用会在称为栈的有限内存区域中累积(参见 声明/定义语句 一节,以及 描述数组 一节中的“堆”和“栈”侧栏),函数迟早会因“栈溢出”运行时错误而终止。这个问题在 FiboEndless 函数中表现出来。

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

请注意,这不是一个编译错误。在这种情况下,编译器甚至不会生成警告(尽管从技术层面上来是可以的)。该错误发生在脚本执行期间。它将被打印终端中的 Experts 日志。

从函数本身调用一个函数时会发生递归。例如,如果 F 函数调用 G 函数,而 G 函数又调用 F 函数,这种情况就是间接递归。因此,递归可以是任何深度的循环调用的结果。