函数逐步减少静态变量,但不应该。 PHP

时间:2016-06-01 21:06:09

标签: php static decrement

有一个功能:

<?php 

 function test(){

     static $count = 0; 
     $count++;  
     echo $count;

     if ($count < 10) {
          test();
     }       

     $count--;  
     echo $count;
}

test();  

?>

此代码生成:123456789109876543210

当$ count递增到10 - 这是可以理解的,它一直有效,直到if语句的计算结果为false。 但为什么它逐渐减少到0? 在我的新手逻辑中,$ count--在这段代码中应该只减少9次,并且函数应该停止。 没有循环或循环可以逐步降低其价值。但我们看到,它在这里工作。 为什么会这样?

2 个答案:

答案 0 :(得分:2)

好的,所以我试着想象一下这里发生了什么,这样你就可以更好地了解发生了什么。

这就是发生的事情(摘要):

//Iteration 1
function(){
    //Code before runs

    if stmt (TRUE)   //Iteration 2   
        function(); → function(){
               ←┐         //Code before runs
    //Code after│
}               │         if stmt (TRUE)          //Iteration 10  
                │             function(); → ... → function(){
                │                        ←┐           //Code before runs
                │         //Code after    │
                │     }                   │           if stmt (FALSE)
                └──── ← function returns  │
                        value and goes    │           //Code after runs
                        back to next line │       }
                                          └────── ← function returns value and goes back to next line


  • 因此,在第10个函数调用中,if语句为FALSE且不再调用函数。

  • 现在第10次调用函数运行到最后并减少变量。

  • 它返回返回值(NULL)并返回上一个函数调用,该函数调用执行函数调用的其余部分,这也会减少变量,等等......

答案 1 :(得分:2)

当您将输出更改为强调条件递归调用的工作原理时,事情可能会更加清晰:

<?php
function test($level=0) {
    static $count = 0;
    $count++;
    echo str_pad('a:', $level+2, ' ', STR_PAD_LEFT), $count, PHP_EOL;

    if ($count < 10) {
        test($level+1);
    }

    $count--;
    echo str_pad('b:', $level+2, ' ', STR_PAD_LEFT), $count, PHP_EOL;
}

test();

打印

a:1
 a:2
  a:3
   a:4
    a:5
     a:6
      a:7
       a:8
        a:9
         a:10
         b:9
        b:8
       b:7
      b:6
     b:5
    b:4
   b:3
  b:2
 b:1
b:0

您的问题似乎是了解函数调用和函数后续返回的工作原理。让我们开始简单

<?php
function c() {
    echo 'c in', PHP_EOL;
    echo 'c out', PHP_EOL;
}

function b() {
    echo 'b in', PHP_EOL;
    c();
    echo 'b out', PHP_EOL;
}

function a() {
    echo 'a in', PHP_EOL;
    b();
    echo 'a out', PHP_EOL;
}

a();

打印

a in
b in
c in
c out
b out
a out
很容易,不是吗?当函数退出/返回时,执行将继续执行调用。并且这不是函数的名称,而是函数调用本身,请参阅例如https://en.wikipedia.org/wiki/Call_stack
所以即使函数调用自己像

<?php
function foo($param) {
    echo "foo($param) in", PHP_EOL;
    if ( $param!==1 ) {
        foo(1);
    }
    echo "foo($param) out", PHP_EOL;
}

foo(0);

不会导致单个退出/返回取消“相同”函数的所有函数调用,但它只会在调用堆栈中冒出一个“范围”/帧。因此输出

foo(0) in
foo(1) in
foo(1) out
foo(0) out

现在将其与上述“改进”脚本的输出进行比较:我希望能为您解决一些问题。