В сообщении в блоге «PHP Internals: When foreach copy» NikiC заявила, что в коде вроде этого:
Фрагмент 1
$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
$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
скопирует массив, потому что, если это не так, переменная $array
в строке 1 будет изменена.
Однако единственное, что foreach
модифицирует около $array
, это указатель внутреннего массива . Итак, почему имеет значение, если внутренний указатель $array
переменной $array
в строке 1 изменен? Это не имело значения в фрагменте 1, почему это имело значение в фрагменте 2?
Почему foreach
необходимо скопировать массив в фрагмент 2, хотя мы не модифицировали его в цикле?
На ваш вопрос ответили в статье, с которой вы связались. Он приведен в разделе
Не указано, refcount> 1
с объяснением того, что требуется копия структур, потому что указатель массива перемещается, и это не должно влиять на внешний массив.
Это связано с тем, что во втором случае массив $ передается по значению функции test()
. Следовательно, внутри функции была сделана копия массива $ , и foreach()
работает с копией. Все будет иначе, если массив $ передается по ссылке на функцию test()
.
Информацию о переходе по значению vs pass by reference см. В этом вопросе