【问题标题】:Does a recursive call to a function instantiate it?对函数的递归调用是否会实例化它?
【发布时间】:2016-08-12 12:38:12
【问题描述】:

我正在尝试理解下面的代码 sn-p 用于计数
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

【问题讨论】:

    标签: vba excel recursion callstack


    【解决方案1】:

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

    程序执行如下:

    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))。然后代码返回到前一个调用者,该调用者调用它的MsgBox 并继续整个返回调用堆栈,返回到每个前一个调用者。

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

    【讨论】:

    • n 个值是如何存储的,n 不应该是静态的吗?所以当它到达 MsgBox(n) 时,它不会只显示 1,而是显示 10 到 1。
    • countup(10) 与 MsgBox(10) 的执行顺序是如何关联的?
    • @你的评论怎么了?
    • @null 我的评论错误地提到它传递了变量n ByVal。我删了。
    • @null 我已经更新了答案,包括一些关于调用堆栈实际发生的事情的评论。希望对您有所帮助。
    【解决方案2】:

    程序首先调用您的子例程/函数countup 并传入值10。然后该值在变量n 中,它是countup 的参数。该函数测试n 的值并使用n - 1 再次调用countup(第一次调用countup 时为9)。 countup 不断被调用,越来越深,n - 1 直到我们降到 1。然后我们开始解开。要解开的最深层收到n,其中包含1,因此它调用MsgBox (n),它显示1。当我们解开到下一层n = 2,所以MsgBox显示2。依此类推,所有的方式备份堆栈。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 然而,因为在这个例子中,n 从未真正改变过——一切正常。
      【解决方案4】:

      虽然我同意“实例化”不是正确的术语,但我认为它可能是一种思考正在发生的事情的有用方式。如果您稍微更改您的 countup 子例程(见下文),以便它现在也存储它传递的参数,那么您实际上将拥有多达 10 个名为“storeN”的变量实例,每个实例都有不同的值。您只能在“当前”版本的 countup 中访问 storeN。但是其余的都在那里,随着递归的展开,将恢复到“早期”的 countup 调用中。

      这实际上正是变量 n 发生的情况。 n 的不同“实例”,当递归展开时,这些“实例”带回来看到日光。这就是为什么 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-04-18
        • 1970-01-01
        • 2015-01-09
        • 1970-01-01
        • 2021-02-20
        • 1970-01-01
        • 2021-04-01
        • 1970-01-01
        相关资源
        最近更新 更多