【问题标题】:PHP: What's the difference between static variable inside a for loop and a non-static variable outside the for loop?PHP:for循环内的静态变量和for循环外的非静态变量有什么区别?
【发布时间】:2011-07-05 04:47:09
【问题描述】:

比如有什么区别

$foobar = 0
for ($i=0; $i<20; $i++) {
    //do something using $foobar
    $foobar++;
}

for ($i=0; $i<20; $i++) {
    static $foobar = 0
    //do something using $foobar
    $foobar++;
}

???

以上两个示例的结果与以下示例不同:

for ($i=0; $i<20; $i++) {
    $foobar = 0
    //do something using $foobar
    $foobar++;
}

所有三种变体都有不同的结果。我知道在三个示例的 first 中,$foobar 变量的值越来越大,而在 第三个​​ 示例中,$foobar 变量的值被重置在每个循环期间。我不确定使用静态 $foobar 变量的示例发生了什么。前两个示例在使用 $foobar 的 for 循环部分中的行为似乎应该相同,但对我而言并非如此。

作为参考,这是我的实际代码(算法尚未完成)。我已经标记了让我思考这个话题的 for() 循环:

function combine($charArr, $k) {

    $currentsize = sizeof($charArr);
    static $combs = array();
    static $originalsize = "unset";
    if ($originalsize === "unset") $originalsize = $currentsize;
    static $firstcall = true;

    if ($originalsize >= $k) {

        $comb = '';
        if ($firstcall === true) { 
            for ($i = $originalsize-$k; $i < $originalsize; $i++) {
                $comb .= $charArr[$i];
            }
            $combs[] = $comb; 
            $firstcall = false; 
        }
        if ($currentsize > $k) { 

            $comb = ''; //reset
            for ($i=0; $i<$k; $i++) { 
                $comb .= $charArr[$i];
            }
            $combs[] = $comb;

            //########### THE FOR LOOP IN QUESTION ###########              
            for ($i = $k-1; $i >= 0; $i--) { 
            static $range_adj = 0;
                for ( $j = $i+1; $j < $currentsize-$range_adj; $j++ ) { 
                    if ( !($i == 0 and $j == $currentsize-$range_adj-1) ) { 
                        $comb = substr_replace($comb, $charArr[$j], $i, 1); 
                        $combs[] = $comb;
                    }
                }
                $range_adj++;
            }
            if ($currentsize-1 > $k) { 
                array_splice($charArr, 0, 1); 
                combine($charArr, $k); 
            }
        }
        $output = array_values( $combs );
        unset($combs);
        return $output;
    }
    else {
        return false;
    }
}

如果我从 for 循环中删除 $range_adj 变量并将其作为 none-static 变量放在所述 for 循环之前,那么我的函数的结果是 相同的。修改后的 for 循环如下所示:

            $range_adj = 0;
            for ($i = $k-1; $i >= 0; $i--) { 
                for ( $j = $i+1; $j < $currentsize-$range_adj; $j++ ) { 
                    if ( !($i == 0 and $j == $currentsize-$range_adj-1) ) { 
                        $comb = substr_replace($comb, $charArr[$j], $i, 1); 
                        $combs[] = $comb;
                    }
                }
                $range_adj++;
            }

我得到两种不同结果的事实使我相信每种方法都有所不同,因为如果两种方法产生相同的结果,那么我的函数的结果在两种情况下都是相同的,这不是我测试这些场景时的情况。为什么我得到两个结果?用实现的 for 循环的两种方法测试我的函数,你也会得到不同的结果。

为方便起见,这里是原始方法:

            for ($i = $k-1; $i >= 0; $i--) { 
                static $range_adj = 0;
                for ( $j = $i+1; $j < $currentsize-$range_adj; $j++ ) { 
                    if ( !($i == 0 and $j == $currentsize-$range_adj-1) ) { 
                        $comb = substr_replace($comb, $charArr[$j], $i, 1); 
                        $combs[] = $comb;
                    }
                }
                $range_adj++;
            }

???

在我看来,结果应该完全相同,但事实并非如此。如果你运行我的函数,你会注意到 for 循环的每个方法都会得到不同的结果。

【问题讨论】:

  • 第二个得到什么结果?
  • 解析错误是可以从所有这些代码中得到的唯一结果;)
  • 上校。弹片,我没有收到解析错误!我在上面发布了我的功能。
  • 说真的。有人可以回答这个问题吗?我已经尽可能详细地更新了!

标签: php static scope


【解决方案1】:

您可以以这种方式使用静态来防止变量在循环内被重新初始化

在第一次迭代中,如果静态变量没有被初始化,那么它将创建它并将其保存在外部上下文中,在每个其他迭代中 PHP 将跳过它,因为它已经被初始化了。

两种结果相同:http://codepad.org/evilks4R

它在你的函数中不同的原因是你的函数是递归的,这意味着函数 combine 调用 combine 从其自身内部,当在第二次调用 combine 时取出 static 关键字时,变量正在 重新初始化 从而使结果不同。

使用 static 关键字允许您将参数传递到第二个调用,其中的值在第三个值中产生。

下面是一个将静态成员传递给函数调用后面传递的示例:http://codepad.org/gChjx7Om

如果你这样做了:

$foo_bar = 0;
for(.....)

这将在一个函数中,这样$foo_bar 将在每次调用该函数时重置为 0,从而覆盖上次调用的计算。

如果您将$foo_bar 移到函数之外,然后在您添加的函数中需要:

global $foo_bar

你会得到相同的结果。

http://www.cprogramming.com/tutorial/statickeyword.html

【讨论】:

  • 所以你是说我的问题中的第一个和第二个例子在技术上应该有相同的结果,对吗???...但是如果你接受我的函数并尝试任何一种形式,你会得到不同的结果。两种形式之间必须有所不同。
  • 为什么我的测试用例会证明不是这样???我一遍又一遍地尝试了这两种形式,并不断得到不同的结果。
  • 我完全理解你的例子并且确切地知道你的意思。但是,我的代码没有相同的行为。看看我的问题的结尾,我已经更新了它,准确地显示了我正在做的修改,显示了两个不同的结果。
  • 你显然不明白我的更新,我解释一下为什么会这样,因为它是一个递归函数,并且每次函数调用都不会重置结果。
  • Aaaaah,所以你是说即使它在 for 循环中,它在所有函数调用中仍然是静态的?我知道了。所以每次我遇到那个 for 循环时,它都会开始在它之前离开的地方增加 $range_adj。我现在明白了。以前,我认为由于我在 for 循环中声明它是静态的,所以它只适用于 for 循环。因此,即使我在 for 循环中声明了一个静态变量,它也会在整个函数中是静态的,对吧?
【解决方案2】:

第一个和第二个循环似乎做同样的事情。这是因为,与任何其他静态初始化变量一样,static 意味着您只初始化一次。当您尝试再次访问它时,它会保留其价值。您会发现无论您声明/初始化它,静态$foobar 仍将存在于循环范围之外;这是由于 PHP 的特性造成的,与静态变量无关。

只有当您尝试在循环之前访问$foobar 时才会清楚区别:它不会在第二个 sn-p 中声明,因为您只在循环中创建它,因此您可能会得到一个 undefined-可变通知。

【讨论】:

  • 感谢您的回答,但我唯一感兴趣的部分是循环内我 //do something using $foobar 的部分。有什么区别?
  • 嘿,我完全理解你的回答,但这并不能解释我的问题。使用我的问题中描述的两种方法时,我得到了不同的结果。
【解决方案3】:

以上两个 prog 具有相同的输出,但您的最后一个 prog 具有在每个循环期间重置的变量。 当您对任何变量初始化使用“静态”关键字时,它会一直保留到您不销毁它为止。或者不销毁您的程序会话。

【讨论】:

  • 我不同意。我的函数(我在上面添加到我的问题中)根据我尝试的方式显示完全不同的输出。
【解决方案4】:

static $foobar = 0;
初始化一次,static $foobar = 0 的其他执行不会对 $foobar 变量做任何事情

【讨论】:

  • 我也是这么想的......但是我得到了完全不同的结果,这意味着有些东西不一样。我在上面添加了我的实际代码。看一看。尝试使用该函数,然后尝试将 static $range_adj 移到 for 循环之外删除 static 关键字。请注意结果不同。
猜你喜欢
  • 1970-01-01
  • 2021-02-24
  • 1970-01-01
  • 1970-01-01
  • 2010-09-25
  • 2011-01-14
  • 1970-01-01
  • 2015-06-11
相关资源
最近更新 更多