对函数的递归调用是否实例化它?

Does a recursive call to a function instantiate it?

我正在尝试理解下面用于计数的代码片段
msgbox 如何存储 n 的所有值?

是不是调用countup(n-1)的时候实例化了这个函数,然后把n值关联到一个msgbox实例?

Option Explicit

Sub countup(n As Integer)   
   If (n > 1) Then
      countup (n - 1)
   End If
   MsgBox (n)
End Sub

Sub myprogram()
   Call countup(10)
End Sub

正如@EdPlunkett 提到的,实例化 与它无关。这涉及创建新对象。这是关于从自身内部调用相同的函数,或 recursion.

程序执行如下:

countup(10) called
  -> countup(9) called
    -> countup(8) called
       -> countup(7) called
          -> countup(6) called
            -> countup(5) called
              -> countup(4) called
                ->countup(3) called
                  ->countup(2) called
                     -> MsgBox (1)
                  -> MsgBox (2)
                -> MsgBox (3)
              -> MsgBox (4)
            -> MsgBox (5)
          -> MsgBox (6)
        -> MsgBox (7)
      -> MsgBox (8)
    -> MsgBox (9)
  -> MsgBox (10)

每次缩进 2 个空格以显示递归调用或退出。

如您所见,在执行第一个 MsgBox 之前,调用堆栈增加到完整的 9 级深度(由于 If (n > 1))。然后代码 return 返回到前一个调用者,后者调用它的 MsgBox 并继续整个过程返回调用堆栈,return 返回到每个先前的调用者。

最后,我们return回到countup(10),执行最后的MsgBox(10),此时我们return到myprogram().

程序首先调用您的 subroutine/function countup 并传入值 10。然后该值位于作为 [=10= 的参数的变量 n 中].该函数测试 n 的值并使用 n - 1 再次调用 countup (第一次调用 countup 时为 9)。 countup 不断被调用,越来越深,n - 1 直到我们降到 1。然后我们开始解开。要解开的最深层收到 n,其中包含 1,因此它会调用 MsgBox (n),显示 1。当我们解开到下一层时,n = 2 显示 MsgBox 2.以此类推,一直往回栈。

将参数传递给 countup(n As Integer) 这样的过程实际上是 countup(byRef n As Integer) 的简短版本。如果您在您的 sub 中更改 n 的值,则调用 n 的值也会更改。

虽然我同意 "instantiate" 不是正确的术语,但我认为它可能是一种思考正在发生的事情的有用方式。如果你稍微改变你的 countup 子例程(见下文),它现在也存储它传递的参数,你真的会有多达 10 个名为 "storeN" 的变量实例,每个实例都有不同的值。您只能在 "current" 版本的 countup 中访问 storeN。但是其余的都在那里,并且随着递归展开,将恢复到 "earlier" countup 调用中。

这基本上就是变量 n 发生的情况。有 个不同的 "instances",随着递归的展开,它们又回到了正轨。这也是为什么 MsgBox 每次调用时显示不同的 n 值的原因。

所以我认为你自己的回答基本正确。

Option Explicit

Sub countup(n As Integer)   
   Dim storeN as Integer
   storeN = n
   If (n > 1) Then
      countup (n - 1)
   End If
   MsgBox (n)
End Sub

Sub myprogram()
   Call countup(10)
End Sub