Почему PHP перезаписывает значения, когда я повторяю этот массив дважды (по ссылке, по значению) - PullRequest
5 голосов
/ 15 апреля 2010

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

$array = range(1,5);
foreach($array as &$element)
{
  $element *= 2;
}
print_r($array);
foreach($array as $element) { }
print_r($array);

Выход:

Массив ([0] => 2 [1] => 4 [2] => 6 [3] => 8 [4] => 10 )

Массив ([0] => 2 [1] => 4 [2] => 6 [3] => 8 [4] => 8 )

Обратите внимание, что я не ищу исправления, я пытаюсь понять, почему это происходит. Также обратите внимание, что этого не происходит, если имена переменных в каждом цикле не называются $element, поэтому я предполагаю, что это связано с тем, что $element все еще находится в области видимости и ссылкой после окончания первого цикла.

Ответы [ 3 ]

7 голосов
/ 15 апреля 2010

После первого цикла $ element по-прежнему является ссылкой на последний элемент / значение $ array.
Вы можете видеть это, когда вы используете var_dump () вместо print_r ()

array(5) {
  [0]=>
  int(2)
...
  [4]=>
  &int(2)
}

Обратите внимание, что & in &int(2).
Во втором цикле вы присваиваете значения элементу $. И поскольку это все еще ссылка, значение в массиве также изменяется. Попробуйте с

foreach($array as $element)
{
  var_dump($array);
}

как второй цикл, и вы увидите.
Так что это более или менее так же, как

$array = range(1,5);
$element = &$array[4];
$element = $array[3];
// and $element = $array[4];
echo $array[4];

(только с циклами и умножением ... эй, я сказал "более или менее"; -))

5 голосов
/ 15 апреля 2010

Вот объяснение самого человека :

$y = "some test";

foreach ($myarray as $y) {
    print "$y\n";
}

Здесь $y - это запись таблицы символов, ссылающаяся на строку, содержащую "some" test ". На первой итерации вы по существу делаете:

$y = $myarray[0];  // Not necessarily 0, just the 1st element

Так что теперь хранилище связано с $y перезаписывается значением из $myarray. Если $y связано с какое-то другое хранилище через ссылка, что хранилище будет Измененное.

Теперь предположим, что вы делаете это:

$myarray = array("Test");
$a = "A string";
$y = &$a;

foreach ($myarray as $y) {
    print "$y\n";
}

Здесь $y связан с тем же хранение как $a через ссылку так когда первая итерация делает:

$y = $myarray[0];

Единственное место, где может "проверяться" строка зайти в хранилище, связанное с $y.

1 голос
/ 04 февраля 2016

Вот как бы вы решили эту проблему:

foreach($array as &$element)
{
    $element *= 2;
}
unset($element); #gets rid of the reference and cleans the var for re-use.

foreach($array as $element) { }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...