当我迭代这个数组两次时,为什么PHP会覆盖值(通过引用,按值)

时间:2010-04-15 13:10:53

标签: php php-5.3

如果我遍历一个数组两次,一次通过引用然后按值迭代,如果我为每个循环使用相同的变量名,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 个答案:

答案 0 :(得分:7)

在第一个循环之后,$ element仍然是对$ array的最后一个元素/值的引用 当使用var_dump()而不是print_r()

时,可以看到
array(5) {
  [0]=>
  int(2)
...
  [4]=>
  &int(2)
}

请注意&在&int(2) 使用第二个循环,您可以为$ element指定值。由于它仍然是一个参考,因此数组中的值也会发生变化。尝试使用

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

作为第二个循环,你会看到。
所以它和

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

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

答案 1 :(得分:5)

这是an explanation from the man himself

$y = "some test";

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

此处$y是一个符号表条目,引用包含“some”的字符串   测试“。在第一次迭代中,你基本上做了:

$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];
     

“Test”字符串唯一可以的地方   go进入与之关联的存储   $y

答案 2 :(得分:1)

这是解决此问题的方法:

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

foreach($array as $element) { }