PHP проходит по ссылке в foreach [дубликат]



этот вопрос уже есть ответ здесь:




  • Странное поведение foreach

    2 ответы



У меня есть этот код:



$a = array ('zero','one','two', 'three');

foreach ($a as &$v) {

}

foreach ($a as $v) {
echo $v.PHP_EOL;
}


может кто-нибудь объяснить, почему вывод:
ноль один два два .



из учебного пособия по сертификации zend.

377   9  
PHP

9 ответов:

потому что на второй цикл, $v по-прежнему является ссылкой на последний элемент массива, поэтому он перезаписывается каждый раз.

вы можете видеть это так:

$a = array ('zero','one','two', 'three');

foreach ($a as &$v) {

}

foreach ($a as $v) {
  echo $v.'-'.$a[3].PHP_EOL;
}

Как вы можете видеть, последний элемент массива принимает текущее значение цикла: "ноль", "один", "два", а затем это просто "два"... :)

мне пришлось потратить несколько часов, чтобы выяснить, почему[3] меняется на каждой итерации. Вот объяснение, к которому я пришел.

в PHP есть два типа переменных: обычные переменные и ссылочные переменные. Если мы назначаем ссылку на переменную другой переменной, переменная становится ссылочной переменной.

например

$a = array('zero', 'one', 'two', 'three');

если мы делаем

$v = &$a[0]

элемент 0-й ($a[0]) становится ссылкой переменная. $v указывает на эту переменную; поэтому, если мы внесем какие-либо изменения в $v, это будет отражено в $a[0] и наоборот.

теперь, если мы делаем

$v = &$a[1]

$a[1] станет ссылочной переменной и $a[0] станет нормальной переменной (так как никто не указывает на $a[0] он преобразуется в нормальную переменную. PHP достаточно умен, чтобы сделать его нормальной переменной, когда никто другой не указывает на нее)

вот что происходит в первом цикле

foreach ($a as &$v) {

}

после последней итерации $a[3] является ссылочной переменной.

С $v указывает $a[3] изменения $v приводит к изменению в $a[3]

во втором контуре,

foreach ($a as $v) {
  echo $v.'-'.$a[3].PHP_EOL;
}

на каждой итерации как $v изменения $a[3] изменения. (потому что $v указан $a[3]). Вот почему $a[3] изменения на каждой итерации.

в итерация перед последней итерацией,$v присваивается значение 'два'. Так как $v указывает на $a[3],$a[3] теперь получает значение 'два'. Имейте это в виду.

в последней итерации, $v (который указывает на $a[3]) теперь имеет значение 'два', потому что $a[3] было установлено значение два в предыдущей итерации. two печати. Это объясняет, почему " два " повторяется, когда $v печатается в последней итерации.

первый круг

$v = $a[0];
$v = $a[1];
$v = $a[2];
$v = $a[3];

да! Ток $v =

Я думаю, что этот код показывает процедуру более ясно.

<?php

$a = array ('zero','one','two', 'three');

foreach ($a as &$v) {
}

var_dump($a);

foreach ($a as $v) {
  var_dump($a);
}

результат: (Обратите внимание на два последних массива)

array(4) {
  [0]=>
  string(4) "zero"
  [1]=>
  string(3) "one"
  [2]=>
  string(3) "two"
  [3]=>
  &string(5) "three"
}
array(4) {
  [0]=>
  string(4) "zero"
  [1]=>
  string(3) "one"
  [2]=>
  string(3) "two"
  [3]=>
  &string(4) "zero"
}
array(4) {
  [0]=>
  string(4) "zero"
  [1]=>
  string(3) "one"
  [2]=>
  string(3) "two"
  [3]=>
  &string(3) "one"
}
array(4) {
  [0]=>
  string(4) "zero"
  [1]=>
  string(3) "one"
  [2]=>
  string(3) "two"
  [3]=>
  &string(3) "two"
}
array(4) {
  [0]=>
  string(4) "zero"
  [1]=>
  string(3) "one"
  [2]=>
  string(3) "two"
  [3]=>
  &string(3) "two"
}

Я попал сюда случайно, и вопрос ОП привлек мое внимание. К сожалению, я не понимаю ни одного объяснения сверху. Мне кажется, что все это знают, понимают, принимают, просто не могут объяснить.

к счастью, чистое предложение из документации PHP на foreach делает это совершенно ясным:

предупреждение: ссылка $value и последний элемент массива остается даже после того, как цикл foreach. Рекомендуется уничтожить его с помощью unset ().

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

foreach ($array as &$row) {
    // Do stuff
    // Unset
    unset($row);
}

это :

$a = array ('zero','one','two', 'three');

foreach ($a as &$v) {

}

foreach ($a as $v) {
    echo $v.PHP_EOL;
}

это то же самое, что

$a = array ('zero','one','two', 'three');

$v = &$a[3];

for ($i = 0; $i < 4; $i++) {
    $v = $a[$i];
    echo $v.PHP_EOL; 
}

или

$a = array ('zero','one','two', 'three');

for ($i = 0; $i < 4; $i++) {
    $a[3] = $a[$i];
    echo $a[3].PHP_EOL; 
}

или

$a = array ('zero','one','two', 'three');

$a[3] = $a[0];
echo $a[3].PHP_EOL;

$a[3] = $a[1]; 
echo $a[3].PHP_EOL;

$a[3] = $a[2];
echo $a[3].PHP_EOL;

$a[3] = $a[3]; 
echo $a[3].PHP_EOL;

Я нашел этот пример также сложнее. Почему во 2-м цикле на последней итерации ничего не происходит ($v остается "два"), заключается в том, что $v указывает на $a[3] (и наоборот), поэтому он не может присвоить себе значение, поэтому он сохраняет предыдущее присвоенное значение:)

потому что если вы создадите ссылку на переменную, все имена для этой переменной (включая оригинал) станут ссылками.

Comments

    Ничего не найдено.