Подтвердить что ты не робот

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

В то время как итерационный массив я использовал одно имя массива для значения ключа foreach($arr as $arr), но он отлично работает. Как это работает?

Почему он не переопределяет значение массива во время итерации?

Я хочу знать, как работает итерация foreach.

Пожалуйста, помогите мне!

Спасибо заранее Логан

4b9b3361

Ответ 1

Почему он не переопределяет значение массива во время итерации?

foreach будет работать над копией исходного массива, поэтому все, что вы измените в цикле foreach, не изменит значения, которые вы зацикливаете.

Ответ 2

PHP использует механизм copy on write или lazy copy с подсчет ссылок для обработки памяти.

На первом этапе итерации foreach $arr "мягко скопирован" (фактическая копия отсутствует, но увеличивается только refcount zval of $array). checkout variable container и label переменных PHP.

В нашем случае

  • сначала сохранить ссылку на фактическую переменную $arr, и первое значение массива извлекается из контрольной точки.
  • Для последующего использования первый элемент массива назначается второму $arr foreach ($ arr как $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

Ответ 3

foreach ($arr as $arr) {
    // code
}

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

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

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

  • PHP запускает операцию foreach, беря значение массива, связанное с $arr
  • он помещает этот массив где-то внутри, скажем, var iterator
  • он принимает текущий элемент из var iterator и продвигает итератор
  • он присваивает значение, которое требуется для $arr в script
  • он выполняет // code
  • он повторяется с шага 3

Другими словами, на каждой итерации он не принимает следующее значение из $arr, оно используется только один раз для получения начального итератора. Фактическая вещь, которую он выполняет, хранится внутри и больше не связана с $arr. Это означает, что $arr является бесплатным для других целей в вашем script, и PHP с удовольствием повторно использует его на каждой итерации. После завершения цикла последний элемент остается в $arr.

Если вы знаете анонимные функции, возможно, это лучше иллюстрирует, почему это работает так, как это работает:

foreach($arr, function ($arr) {
    // code
});

Реализация такой функции foreach может быть просто следующей:

function foreach(array $array, callable $code) {
    while (list(, $value) = each($array))  {
        $code($value);
    }
}

Ответ 4

$arr и $arr одинаковы в вашем коде. Массив источника и ссылочная переменная имеют одинаковое имя. Так что foreach сохраняет значение, которое было получено последним, оно не отбрасывает переменную.

Ответ 5

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 - 3.

Ответ 6

вы закончите запись массива при извлечении записи, вы просите код извлечь запись из $arr и поместить ее в массив с именем $arr, чтобы вы закончили запись всего массива с помощью одного параметра до $ arr = {1,2,3}; после этой строки и первой итерации foreach ($ arr as $arr) теперь $arr равен 3, который является последним элементом массива, надеюсь, вы столкнулись с проблемой

Ответ 7

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

<?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, он внутренне отключает символ ($arr)

Ответ 8

foreach сначала оценивает левую сторону перед повторением своих элементов. Поэтому переназначение на имя $arr не изменяет $arr.

Кроме того, переменная цикла течет во внешний контекст, поскольку документально:

Ссылка a $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;