我有这样的代码:

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

foreach ($a as &$v) {

}

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

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

来自zend认证学习指南。


当前回答

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

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

其他回答

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

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

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

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

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

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

我不得不花几个小时来弄清楚为什么[3]在每次迭代中都会发生变化。这就是我得出的解释。

在PHP中有两种类型的变量:普通变量和引用变量。如果将一个变量的引用赋给另一个变量,该变量就成为引用变量。

例如在

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

如果我们这样做

$v = &$a[0]

第0个元素($a[0])成为一个引用变量。$v指向这个变量;因此,如果我们对$v做了任何更改,它将反映在$a[0]中,反之亦然。

如果我们这样做

$v = &$a[1]

$a[1]将成为一个引用变量,$a[0]将成为一个普通变量(由于没有其他人指向$a[0],它将被转换为一个普通变量。PHP足够聪明,当没有人指向它时,它是一个正常的变量)

这是在第一个循环中发生的事情

foreach ($a as &$v) {

}

在最后一次迭代之后,$a[3]是一个引用变量。

因为$v指向$a[3],对$v的任何改变都会导致$a[3]的改变

在第二个循环中,

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

在每次迭代中,随着$v的变化,$a[3]也会发生变化。(因为$v仍然指向$a[3])。这就是$a[3]在每次迭代中更改的原因。

在上一次迭代之前的迭代中,$v被赋值为'two'。由于$v指向$a[3], $a[3]现在得到的值为“2”。记住这一点。

在最后一次迭代中,$v(指向$a[3])现在的值为“2”,因为$a[3]在前一次迭代中被设置为2。2打印出来了。这解释了为什么在最后一次迭代中打印$v时重复'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;