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的所有名称(包括原始)成为参考。