PHP5和PHP7 foreach循环问题

PHP7 升级手册中提及了"foreach 通过值遍历时,操作的值为数组的副本. 当默认使用通过值遍历数组时,foreach 实际操作的是数组的迭代副本,而非数组本身。这就意味着,foreach 中的操作不会修改原数组的值。" 我以为PHP5的foreach循环是数组本身, 于是验证一下, 结果跟我想的不一样. 但是我查询资料时候看到一个代码, 让我感觉有所疑惑. 麻烦解答一下我疑惑

$array = array('a', 'b', 'c');
$ref = &$array;
foreach ($array as $val) {
    $array[3] = 'd';
    print_r($array);
    echo '迭代的值: ' . $val . "\n";
}

PHP7输出的结果:

clipboard.png

PHP5输出结果:

clipboard.png

只是把数组引用一下, 为什么会出现不一样结果? 去掉引用, PHP7和PHP5结果是一样的, 到底PHP5中foreach循环操作数组是数组本身还是数组的副本?

阅读 5.1k
1 个回答

研究一个晚上, 大概懂了一些. 总体上来说, PHP 5 在foreach通过值遍历时还是会拷贝数组的. 但是PHP 7 内部实现这个迭代数组与 PHP 5 不同.PHP 7 不在依靠数组内部指针, 而PHP5是靠内部指针的. 验证PHP 5 在foreach下是否拷贝了数组

$arr = [0];
foreach ($arr as $k => $v) {
    debug_zval_dump($arr);
}

打印出来的refcount为3, 说明在foreach中拷贝数组了, 导致refcount为3. 进一步验证.

$arr = [0];
foreach ($arr as $v) {
    $copy = $arr;
    debug_zval_dump($arr);
}

假设数组在循环中拷贝了, 那么refcount应该为4. 其打印结果跟我猜想一样. 说明数组在foreach进行拷贝了. 而且不受数组的长度影响. 因为数组长度为2时候, 还是打印4.在PHP5 foreach靠的是数组指针在移动从而达到迭代数组的值.

$arr = [0, 1];
foreach ($arr as $v) {
    $copy = $arr;
    debug_zval_dump($arr);
}

foreach是如何运行的

深入理解PHP原理之变量分离/引用(Variables Separation)

当我们使用foreach时,内部究竟发生了什么(PHP5)?

推荐问题
宣传栏