我有这样的代码:

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

foreach ($a as &$v) {

}

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

有人能解释一下为什么输出是: 零一二二。

来自zend认证学习指南。


当前回答

第一个循环

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

是的!当前$v = $a[3]位置。

第二个循环

$a[3] = $v = $a[0], echo $v; // same as $a[3] and $a[0] == 'zero'
$a[3] = $v = $a[1], echo $v; // same as $a[3] and $a[1] == 'one'
$a[3] = $v = $a[2], echo $v; // same as $a[3] and $a[2] == 'two'
$a[3] = $v = $a[3], echo $v; // same as $a[3] and $a[3] == 'two'

因为$a[3]在处理前被分配。

其他回答

第一个循环

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

是的!当前$v = $a[3]位置。

第二个循环

$a[3] = $v = $a[0], echo $v; // same as $a[3] and $a[0] == 'zero'
$a[3] = $v = $a[1], echo $v; // same as $a[3] and $a[1] == 'one'
$a[3] = $v = $a[2], echo $v; // same as $a[3] and $a[2] == 'two'
$a[3] = $v = $a[3], echo $v; // same as $a[3] and $a[3] == 'two'

因为$a[3]在处理前被分配。

我是偶然来到这里的,而警官的问题引起了我的注意。不幸的是,我不明白高层的任何解释。在我看来,每个人都知道它,明白它,接受它,只是无法解释。

幸运的是,PHP文档中关于foreach的一句话完全说明了这一点:

警告:即使在foreach循环之后,$值和最后一个数组元素的引用仍然存在。建议使用unset()来销毁它。

我认为这段代码更清楚地显示了程序。

<?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"
}

我发现这个例子也很棘手。为什么在最后一次迭代的第二个循环中什么都没有发生($v保持' 2 '),是因为$v指向$a[3](反之亦然),所以它不能给自己赋值,所以它保持之前赋值:)

因为在第二个循环中,$v仍然是对最后一个数组项的引用,所以它每次都会被覆盖。

你可以这样看:

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

foreach ($a as &$v) {

}

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

如你所见,最后一个数组项接受当前循环值:'zero', 'one', 'two',然后它只是'two'…:)