当我两次通过此数组迭代时,为什么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)
}

请注意&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];

(只有循环和乘法...嘿,我说“或多或少” ;-))

其他提示

这是 男人本人的解释:

$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