PHP的foreach()如何成功嵌套在一个数组上?

时间:2015-05-30 10:07:39

标签: php-internals

请考虑以下代码:

$a = [1, 2, 3];

foreach ($a as $x) {
    foreach ($a as $y) {
        echo "$x $y\n";
    }
}

正如人们所料,它给出了以下结果:

1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3

虽然对结果感到满意,但我很惊讶它有效,因为根据manual,它依赖于数组的内部指针:

  

当foreach首次开始执行时,内部数组指针会自动重置为数组的第一个元素。这意味着您不需要在foreach循环之前调用reset()。

     

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

所以我们可以期望在第一个内部使用嵌套的foreach,它将共享相同的内部指针,并产生以下结果:

1 1
1 2
1 3

因为第一个foreach会看到嵌套foreach留下的内部指针的状态。

我可以想到对实际行为的两种可能的解释:

  • PHP手册错误/过时,PHP使用特定于每个foreach的单独指针;
  • 嵌套的foreach在内部触发了数组在内存中的重复,因此它们每个都有自己的指针。

仅仅因为我的文化,这是如何在内部发挥作用的?

1 个答案:

答案 0 :(得分:4)

简短回答。在这种情况下,PHP确实复制了数组(即数组 structure )。 Foreach可以在各种场景中做到这一点,以防止这样的问题。有些人认为foreach 总是复制数组,但事实并非如此(效率低下)。

我发现了一篇很棒的博文,更详细地描述了这种行为:

PHP internals: When does foreach copy?

摘要:

    当且仅当迭代时,
  • foreach才会复制数组结构 数组未被引用并且具有引用计数> 1
  • foreach会的 另外复制数组当前和仅当前一点 适用,迭代由参考
  • 完成