递归如何使运行时内存的使用变得不可预测?

时间:2010-11-02 18:23:32

标签: language-agnostic memory memory-management recursion factorial

引自Code Complete 2

int Factorial( int number ) {
   if ( number == 1 ) {
      return 1;
   }
   else {
      return number * Factorial( number - 1 );
   }
}
     

除了 [1] 以及制作   使用运行时内存   不可预测的 [2] ,递归版本   这个例程很难   理解比迭代版本,   以下是:

int Factorial( int number ) {
   int intermediateResult = 1;
   for ( int factor = 2; factor <= number; factor++ ) {
      intermediateResult = intermediateResult * factor;
   }
   return intermediateResult;
}

我认为缓慢的部分是因为不必要的函数调用开销。

但递归如何使运行时内存的使用变得不可预测?

我们不能总是预测需要多少内存(正如我们知道递归应该结束的时候)?我认为这与迭代案例一样不可预测,但现在不再存在。

3 个答案:

答案 0 :(得分:3)

由于递归方法反复调用自身的事实,需要大量的堆栈内存。由于堆栈有限,如果超出堆栈内存,将发生错误。

答案 1 :(得分:1)

  

我们不能总是预测需要多少内存(正如我们知道递归应该结束的时候)?我认为这与迭代案例一样不可预测,但现在不再存在。

不,不是一般情况。有关更多背景信息,请参阅有关halting problem的讨论。现在,这里是其中一个问题的递归版本:

void u(int x) {
    if (x != 1) {
        u((x % 2 == 0) ? x/2 : 3*x+1);
    }
}

它甚至是尾递归的。由于您无法预测这是否会正常终止,您如何预测需要多少内存?

答案 2 :(得分:0)

如果递归级别变得太深,那么你将会打破调用堆栈并在此过程中占用大量内存。如果您的number是一个“足够大”的值,就会发生这种情况。你能做比这更糟糕的事吗?是的,如果你的函数在每次递归调用时都分配了更多的对象。