我有这样的代码:
$a = array ('zero','one','two', 'three');
foreach ($a as &$v) {
}
foreach ($a as $v) {
echo $v.PHP_EOL;
}
有人能解释一下为什么输出是: 零一二二。
来自zend认证学习指南。
我有这样的代码:
$a = array ('zero','one','two', 'three');
foreach ($a as &$v) {
}
foreach ($a as $v) {
echo $v.PHP_EOL;
}
有人能解释一下为什么输出是: 零一二二。
来自zend认证学习指南。
当前回答
我不得不花几个小时来弄清楚为什么[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'。
其他回答
第一个循环
$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]在处理前被分配。
因为如果您创建了一个变量的引用,那么该变量的所有名称(包括原始名称)都将成为引用。
这样的:
$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 = array ('zero','one','two', 'three');
foreach ($a as &$v) {
}
foreach ($a as $v) {
echo $v.'-'.$a[3].PHP_EOL;
}
如你所见,最后一个数组项接受当前循环值:'zero', 'one', 'two',然后它只是'two'…:)
我认为这段代码更清楚地显示了程序。
<?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"
}