Recursion 为什么当您以递归方式返回时,堆栈中的项不会立即弹出?

Recursion 为什么当您以递归方式返回时,堆栈中的项不会立即弹出?,recursion,stack,Recursion,Stack,好吧,这可能是个愚蠢的问题。但我认为,每当你返回一些东西时,堆栈中的项目就会弹出。但是在递归的情况下,堆栈中的项不断堆积,直到到达基本情况。然后它开始爆炸。我想知道这是为什么 还有,一个项目什么时候从堆栈中弹出 谢谢,例如: def bar(n): if n > 0: print(n) return bar(n-1) return 'end' 在returnbarn-1语句中,我们首先执行barn-1,然后返回barn-1的返回值 当我们执

好吧,这可能是个愚蠢的问题。但我认为,每当你返回一些东西时,堆栈中的项目就会弹出。但是在递归的情况下,堆栈中的项不断堆积,直到到达基本情况。然后它开始爆炸。我想知道这是为什么

还有,一个项目什么时候从堆栈中弹出

谢谢,例如:

def bar(n):
    if n > 0:
        print(n)
        return bar(n-1)
    return 'end'
在returnbarn-1语句中,我们首先执行barn-1,然后返回barn-1的返回值

当我们执行barn-1时,我们将遇到类似的情况,除非n>0不再为真

这就是为什么我们可以有递归

也许我的解释很无聊,我想和你分享一个,你真的很想看一看。

我将按项假设,你指的是函数的堆栈框架,而不是像调用堆栈一样运行的函数中的项元素。我希望澄清关于调用堆栈如何工作的困惑

还要注意,a中的每个都有自己的调用堆栈。现在,假设我们使用的是一个进程,该进程有一个正在运行的执行线程

递归函数是一个调用自身的函数。无论何时调用函数,到达函数调用指令的线程都会创建堆栈帧。堆栈帧是包含执行被调用函数变量、参数等所需的所有数据的内存块。此帧被推到调用堆栈的顶部。当前正在执行的调用函数暂时挂起,堆栈指针向上移动到新帧,然后执行新帧

如果没有基本情况,或者函数不再进行递归调用的条件状态,递归将无限期地进行。当发生这种情况时,操作系统会发送一个信号,当进程超过其堆栈使用量(通常为1MB)时终止进程

在到达基本情况并执行函数中的最后一行代码后,线程开始自上而下解析堆栈帧,在完成执行时将其从堆栈中弹出—它们可能会做更多的工作或进行其他递归调用

pop相当于释放与帧关联的内存,处理返回值,将堆栈指针移回调用方,并在发出调用的位置继续执行

下面是一个C和Python的示例程序,其中包含一个递归函数和一个图表:

#include <stdio.h>

void count_to(int n) {
    if (n > 0) {
        count_to(n - 1);
    }

    printf("%d\n", n);
}

int main() {
    count_to(4);
    return 0;
}
以下是程序的输出:

0 1. 2. 3. 4. 以下是执行期间调用堆栈的外观:

[count_to(4)]  <-- top of call stack/stack pointer
[main]         <-- bottom of call stack
最后,执行返回main,main退出


我建议阅读wikipedia的文章,如和,并编写许多类似于此处示例的微型递归程序,以了解它们是如何工作的。

具体哪一项?当前的stackframe确实在返回时从堆栈中弹出,甚至在递归函数调用时也是如此。但是在返回之前进行递归调用,这就是递归的原因。
[count_to(3)]  <-- 
[count_to(4)]  
[main]         
[count_to(3)]  <--
[count_to(4)]
[main]         
[count_to(2)]  <-- 
[count_to(3)]
[count_to(4)]
[main]         
[count_to(1)]  <--
[count_to(2)]
[count_to(3)]
[count_to(4)]
[main]         
[count_to(0)]  <--
[count_to(1)]
[count_to(2)]
[count_to(3)]
[count_to(4)]
[main]         
print(0)
return

[count_to(1)]  <-- 
[count_to(2)]
[count_to(3)]
[count_to(4)]
[main]         
print(1)
return

[count_to(2)]  <-- 
[count_to(3)]
[count_to(4)]
[main]         
print(2)
return

[count_to(3)]  <--
[count_to(4)]
[main]         
print(3)
return

[count_to(4)]  <--
[main]         
print(4)
return

[main]         <--