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
}

это может сбить вас с толку, потому что ваша ментальная модель того, как это работает:

  1. PHP берет текущий элемент из $arr и выдвигает указатель массива
  2. он присваивает значение $arr
  3. выполняется // code
  4. он повторяется с первого шага

что он на самом деле делает, хотя это (или, по крайней мере, приблизительное его упрощение):

  1. PHP запускает foreach операция, принимая значение массива, которое связано с $arr
  2. он помещает этот массив где-то внутри, скажем var iterator
  3. он принимает текущий элемент из var iterator и перемещает итератор
  4. он присваивает значение, которое потребовалось, чтобы $arr в свой скрипт
  5. выполняется // code
  6. это повторяется с шага 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;