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

StackOverflow https://stackoverflow.com/questions/2645499

  •  27-09-2019
  •  | 
  •  

Вопрос

Если я повторяю через массив дважды, один раз в качестве ссылки, а затем по значению, 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 Все еще находиться в области применения и ссылку после окончания первого цикла.

Это было полезно?

Решение

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

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

Обратите внимание, что и в &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];

(Только с петлями и умножением ... Эй, я сказал «более или менее» ;-))

Другие советы

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

$y = "some test";

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

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

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

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

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

foreach($array as $element) { }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top