5

这真让我抓狂。递归函数在 5.4.4 和 5.1.6(我无法控制的客户端的托管服务器)中的工作方式似乎有所不同。除了举例,我无法真正解释它:

<?php
$simpsons[0] = array("name"=>"Abe","parent"=>-1);
$simpsons[1] = array("name"=>"Homer","parent"=>0); // Homer's parent is Abe
$simpsons[2] = array("name"=>"Bart","parent"=>1); // Bart's parent is Homer
$simpsons[3] = array("name"=>"Lisa","parent"=>1); // Lisa's parent is Homer
$simpsons[4] = array("name"=>"Maggie","parent"=>1); // Maggie's parent is Homer


function get_children($parent) {
    global $simpsons;

    foreach ($simpsons as $index=>$onesimpson) {
        if ($onesimpson["parent"]==$parent) {
            echo "$onesimpson[name] is a child of ".$simpsons[$parent]["name"].".<br />\n";
            get_children($index);
        }
    }
}

get_children(0);
?>

在 PHP 5.4.4 上,输出是

Homer is a child of Abe.
Bart is a child of Homer.
Lisa is a child of Homer.
Maggie is a child of Homer.

而在 PHP 5.1.6 上的输出是

Homer is a child of Abe.
Bart is a child of Homer.

我不擅长术语,所以我无法解释发生了什么(就像在 5.1.6 中,即使被调用函数完成,被调用函数也会改变调用函数的参数),但我已经在 PHP 沙箱在线测试过在这两个版本上,问题是相同的 - 它不是特定于我的设置或托管服务器设置。

4

2 回答 2

8

我不确定是什么改变使它在 5.2 中开始工作,但是一个数组只有一个内部指针(这是 foreach 使用的),所以当你使用这样的全局数组时,你会在最高版本中看到结果5.2 很有意义。您启动一个 foreach 循环,内部指针前进,然后递归调用 get_children,启动另一个 foreach 循环,内部指针重置,然后遍历数组。

当您返回被调用者时,内部指针将已经位于数组的末尾,并且 foreach 循环将完成。引用手册

由于 foreach 依赖于内部数组指针,因此在循环内更改它可能会导致意外行为。

在同一个数组的 foreach 中使用 foreach 就是一个例子。

编辑我发现了一些在 5.2.1 版中标记为已修复的相关错误报告:

事实证明,foreach 可以在数组的克隆上工作,因此嵌套 foreach 循环是完全有效的,这确实是一个错误,直到 5.2.1 版本才在 foreach 循环中克隆数组引用。

于 2013-08-21T16:34:32.013 回答
3

我已经稍微调整了你的代码。显然,当您将$simpsons数组引用作为参数传递给递归函数时,它适用于所有版本。

$simpsons = array();
$simpsons[0] = array("name"=>"Abe","parent"=>-1);
$simpsons[1] = array("name"=>"Homer","parent"=>0); // Homer's parent is Abe
$simpsons[2] = array("name"=>"Bart","parent"=>1); // Bart's parent is Homer
$simpsons[3] = array("name"=>"Lisa","parent"=>1); // Lisa's parent is Homer
$simpsons[4] = array("name"=>"Maggie","parent"=>1); // Maggie's parent is Homer


function get_children($simpsons, $parent) {
  foreach ($simpsons as $index=>$onesimpson) {
    if ($onesimpson["parent"]==$parent) {
      echo "$onesimpson[name] is a child of ".$simpsons[$parent]["name"].".<br />\n";
      get_children($simpsons, $index);
    }
  }
}

get_children($simpsons, 0);
于 2013-08-21T16:29:45.800 回答