PHP在foreach中通过引用传递

我有这个代码:

$a = array ('zero','one','two', 'three'); foreach ($a as &$v) { } foreach ($a as $v) { echo $v.PHP_EOL; } 

有人可以解释为什么输出是:零一二二。

从zendauthentication学习指南。

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

你可以这样看:

 $a = array ('zero','one','two', 'three'); foreach ($a as &$v) { } foreach ($a as $v) { echo $v.'-'.$a[3].PHP_EOL; } 

正如你所看到的,最后一个数组项取当前循环值:'零','一','二',然后它只是'两'…)

我不得不花上几个小时来弄清楚为什么每次迭代都会改变。 这是我到达的解释。

PHP中有两种types的variables:正常variables和引用variables。 如果我们将一个variables的引用赋值给另一个variables,variables就变成了一个引用variables。

例如

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

如果我们这样做

 $v = &$a[0] 

第0个元素( $a[0] )成为一个参考variables。 $v点对这个variables; 因此,如果我们对$v进行任何更改,它将反映在$a[0] ,反之亦然。

现在如果我们这样做

 $v = &$a[1] 

$a[1]将成为一个引用variables, $a[0]将成为一个普通variables(因为没有其他人指向$a[0]它被转换成一个正常的variables。当没有其他人指向它时是正常variables)

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

 foreach ($a as &$v) { } 

在最后一次迭代之后, $a[3]是一个参考variables。

由于$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]现在得到值“two”。 记住这一点。

在上一次迭代中, $v (指向$a[3] )现在具有'two'的值,因为在上一次迭代中$a[3]被设置为2。 two是打印。 这解释了为什么在上次迭代打印$ v时重复“two”。

第一个循环

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

我只是偶然来到这里,OP的问题引起了我的注意。 不幸的是,我不明白上面的任何解释。 对我来说似乎每个人都知道,得到它,加上它,就是无法解释。

幸运的是,从foreach上的PHP文档中得到一个纯粹的句子,这完全清楚:

警告:即使在foreach循环之后,引用$value和最后一个数组元素也会保留。 build议通过unset()来销毁它。

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

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

这个 :

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

要么

 $a = array ('zero','one','two', 'three'); for ($i = 0; $i < 4; $i++) { $a[3] = $a[$i]; echo $a[3].PHP_EOL; } 

要么

 $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保留两个),$ v指向$ a [3](反之亦然),所以它不能赋值给自己,所以它保持先前分配的值:)

因为如果您创build一个variables的引用,该variables的所有名称(包括原始)成为参考。