Php foreach-почему он не переопределяет значение массива во время итерации?
у меня есть сомнения в PHP foreach для итерации.
пожалуйста, посмотрите мой код ниже.
код :
$arr=array(1,2,3);
echo '$arr value : '. $arr;
echo '<br>';
foreach($arr as $arr){
echo $arr.'<br>';
}
echo '$arr value : '. $arr;
выход :
$arr value : Array
1
2
3
$arr value : 3
при итерации массива я использовал то же имя массива для значения key foreach($arr as $arr)
но он отлично работает. Как это работает?.
почему он не переопределяет значение массива при переборе?
Я хочу знать,как работает итерация foreach.
пожалуйста, помогите мне!
спасибо заранее Логан!--9-->
8 ответов
почему он не переопределяет значение массива при переборе?
foreach будет работать над копией исходного массива, поэтому вещи, которые вы меняете в цикле foreach, не изменят значения, которые вы зацикливаете.
PHP использует copy on write
или lazy copy
механизм подсчет ссылок для работы с оперативной памятью.
на первом этапе итерации foreach $arr
"мягко скопировано" (нет фактической копии, но только refcount
на zval
of $array
увеличивается). оформить заказ variable container
и label
переменных PHP.
в нашем случае,
- сначала сохраните ссылку на фактический
$arr
переменная, и первое значение массива извлечено из контрольной точки. - для последующего использования первый элемент массива присваивается второму
$arr
foreach ($arr as $arr) - на следующей итерации второе значение массива извлекается из ранее сохраненной опорной точки, и это значение присваивается тому же
$arr
и продолжается. - в значение
$arr
изменяется внутри цикла, вы не можете распечатать этот массив вне цикла, используя$arr
переменной.
надеюсь, что вы можете понимать...
для углубленного изучения проверки http://www.php.net/manual/en/internals2.opcodes.fe-fetch.php и http://www.php.net/manual/en/internals2.opcodes.fe-reset.php
интересно, что вы можете играть с этим тоже...
current()
внутри цикла foreach всегда возвращает один и тот же элемент!!!
код
$source = array(10, 20, 30);
foreach ($source as $value) {
echo 'Value is ', $value, ', and current() is ', current($source), '<br>';
}
выход
Value is 10, and current() is 20
Value is 20, and current() is 20
Value is 30, and current() is 20
foreach ($arr as $arr) {
// code
}
это может сбить вас с толку, потому что ваша ментальная модель того, как это работает:
- PHP берет текущий элемент из
$arr
и выдвигает указатель массива - он присваивает значение
$arr
- выполняется
// code
- он повторяется с первого шага
что он на самом деле делает, хотя это (или, по крайней мере, приблизительное его упрощение):
- PHP запускает
foreach
операция, принимая значение массива, которое связано с$arr
- он помещает этот массив где-то внутри, скажем
var iterator
- он принимает текущий элемент из
var iterator
и перемещает итератор - он присваивает значение, которое потребовалось, чтобы
$arr
в свой скрипт - выполняется
// code
- это повторяется с шага 3
другими словами, он не принимает следующее значение из $arr
на каждый итерации, он использовал только один раз, чтобы получить начальный итератор. Фактическая вещь, которую он перебирает, хранится внутри и не связана с
$arr и $arr одинаковы в вашем коде.Исходный массив и ссылочная переменная имеют одинаковое имя.Таким образом, foreach сохраняет значение, которое было получено последним, оно не отказывается от переменной.
foreach
используйте копию исходного массива, чтобы вы могли думать, что код
foreach($arr as $arr){
echo $arr.'<br>';
}
как раз как ниже:
for ($i = 0, $arr_tmp = $arr, $len = count($arr_tmp); $i < $len; $i++) {
$arr = $arr_tmp[$i];
echo $arr.'<br>';
}
Это объясняет, почему $arr
is 3
наконец-то.
вы пишете массив при извлечении записи, вы просите код извлечь запись из $arr и поместить ее в массив с именем $arr, чтобы вы написали весь массив с одним параметром до $arr = {1,2,3}; после этой строки и первой итерации foreach ($arr как $arr) теперь $arr равен 3, который является последним элементом массива, я надеюсь, что вы стоите перед проблемой
Мда, после небольшого расследования я придумал этот код:
<?php
$arr=array(1,2,3);
echo '$arr value : '. $arr;
echo '<br>';
foreach($arr as $arr){
echo $arr.'<br>';
}
foreach($arr as $key) {
echo $key.'<br>';
}
echo '$arr value : '. $arr;
который имел этот выход:
$arr value : Array
1
2
3
PHP Warning: Invalid argument supplied for foreach() in ...file...
мой взгляд на это, что второй $arr
затеняет первый, находясь внутри foreach
петли, но как только он выходит foreach
loop он внутренне отключает символ ($arr
)
foreach
сначала оценивает левую сторону перед итерацией по ее элементам. Поэтому переназначение имени $arr не изменяет $arr.
кроме того, переменная цикла утечки во внешний контекст, как документирована:
ссылка
$value
и последний элемент массива остается даже после цикла foreach. Рекомендуется уничтожить его с помощью unset ().
конечно, избегайте путаницы, вы должны просто использовать другое имя для переменной цикла, чем для массива, который вы зацикливаете:
$arr=array(1,2,3);
foreach($arr as $a) { // Note the "as $a", not "as $arr"
echo $a.'<br>';
}
echo '$arr value : '. $arr;