我有这样的代码:

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

foreach ($a as &$v) {

}

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

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

来自zend认证学习指南。


当前回答

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

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

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

其他回答

这个问题提供了很多解释,但没有明确的例子说明如何解决这种行为导致的问题。在大多数情况下,您可能需要在通过引用foreach传递的代码中使用以下代码。

foreach ($array as &$row) {
    // Do stuff
}
// Unset to remove the reference
unset($row);

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

幸运的是,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"
}

这样的:

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

foreach ($a as &$v) {

}

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

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

$v = &$a[3];

for ($i = 0; $i < 4; $i++) {
    $v = $a[$i];
    echo $v.PHP_EOL; 
}

OR

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

for ($i = 0; $i < 4; $i++) {
    $a[3] = $a[$i];
    echo $a[3].PHP_EOL; 
}

OR

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

$a[3] = $a[0];
echo $a[3].PHP_EOL;

$a[3] = $a[1]; 
echo $a[3].PHP_EOL;

$a[3] = $a[2];
echo $a[3].PHP_EOL;

$a[3] = $a[3]; 
echo $a[3].PHP_EOL;

第一个循环

$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]在处理前被分配。