关于php:为什么foreach在我们没有在循环中修改它时复制数组?

Why does foreach copy the array when we did not modify it in the loop?

本问题已经有最佳答案,请猛点这里访问。

在"php内部:foreach什么时候复制"的博客文章中,nikic在这样的代码中指出:

片段1

1
2
3
4
$array = range(0, 100000);
foreach ($array as $key => $value) {
    xdebug_debug_zval('array'); // array is not copied, only refcount is increased
}

foreach不会复制数组,因为foreach修改的关于$array的唯一内容是它的内部数组指针。

他还指出,在这样的代码中:

片段2

1
2
3
4
5
6
7
8
$array = range(0, 100000); // line 1
test($array);
function test($array) {
    foreach ($array as $key => $value) { // line 4
        xdebug_debug_zval('array'); // array is copied, refcount not increased
        // ...
    }
}

foreach将复制数组,因为如果没有,第1行中的$array变量将被更改。

但是,foreach修改的关于$array的唯一内容是它的内部数组指针。那么,如果第1行中的$array变量的内部数组指针发生了更改,为什么这一点很重要?在代码片段1中并不重要,为什么在代码片段2中如此重要?

为什么foreach需要复制片段2中的数组,即使我们没有在循环中修改它?


这是因为在第二种情况下,$array是按值传递给函数test()。因此,在函数内部生成了$array的副本,而foreach()在副本上工作。如果通过对函数test()的引用传递$array,情况会有所不同。

有关传递值与传递引用的信息,请参见此问题


你的问题在你链接的文章中得到了回答。本节给出了

Not referenced, refcount > 1

其中解释了由于数组指针移动而需要结构的副本,并且这不得影响外部数组。