关于PHP FOREACH的一个问题

2013-09-07 21:52:45 +08:00
 ovear
<?php
$ww = array(123,456,789);
$qq = array(1,2,3);


foreach ($ww as &$v) {}

foreach ($qq as $v) {}

print_r ($ww);
print_r ($qq);

?>

这段代码结果是

Array ( [0] => 123 [1] => 456 [2] => 3 ) Array ( [0] => 1 [1] => 2 [2] => 3 )

为什么 $ww[2]会变成3呢
4212 次点击
所在节点    PHP
14 条回复
GordianZ
2013-09-07 21:58:54 +08:00
http://php.net/manual/en/control-structures.foreach.php

Warning
Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset().
mengzc
2013-09-07 23:14:15 +08:00
@GordianZ 能不能通俗点啊?我试验了半天,还不是很清楚。
bixuehujin
2013-09-07 23:27:32 +08:00
第一个foreach结束后$v还可以访问,而且是$ww[2]的引用,第二个foreach每循环一次$ww[2]就被重写一次。

所以最后$ww[2]值为3
mengzc
2013-09-07 23:57:21 +08:00
现在知道了~~foreach ($qq as $v) {}
这个运行完以后吧$v的值变了,所以 $ww[2]会变成3。
如果你把两个foreach,更换顺序,结果就不一样咯,但是实际上还是把值变了,只是两个值一样。
mengzc
2013-09-08 00:06:24 +08:00
@bixuehujin 为什么改变$v的值会把$ww[2]的值改变呢?
osinx
2013-09-08 00:28:02 +08:00
两行foreach之间加再加一句 
unset($v);

再看看执行的结果。
msg7086
2013-09-08 00:55:47 +08:00
@mengzc 因为$v引用了$ww数组的最后一个元素。

楼主文中的
》foreach ($ww as &$v) {}

》$v = &$ww[2];
等效。
而后的
》foreach ($qq as $v) {}

》$v = $qq[2];
以及
》$ww[2] = $qq[2];
等效。

不知能不能明白?
anewg
2013-09-08 09:28:01 +08:00
1楼早已给出答案,楼主要是懒得看英文,手册里有选项“view this page in”直接选中文就好了。

“数组最后一个元素的 $value 引用在 foreach 循环之后仍会保留。建议使用 unset() 来将其销毁。”

你要是foreach中用了&,则 foreach ($ww as &$v){} 中的$v(第一个foreach结束后$v引用在$ww的最后一个元素,也就是$ww[2]上)

在之后的foreach中仍然是可以访问到$v($ww[2])的。而且不仅仅是foreach,只要你在之后的脚本中对$v赋值,都是会间接改变你的$ww[2](效果跟$v = &$ww[2]是一样的)

所以你foreach里要是使用了引用,foreach结束后用unset($v);清除对 $ww[2] 的引用,消除后续语句对$ww[2]的影响.(楼主也可以改变你的第二个foreach为foreach ($qq as $q){},这样就没有使用到$v了)
lvni
2013-09-08 11:03:28 +08:00
第一个循环结束之后
foreach ($ww as &$v) {}

$v是指向$ww 最后一个值的引用

此时如果对 $v 赋值都会改变 $ww 最后一个元素的值
例如 :$v = 'someValue';
则:
$ww = Array
(
[0] => 123,
[1] => 456,
[2] => 'someValue'
)

第二个循环遍历逐个将 $qq 的元素赋值给 $v;
循环结束时刚好是 $v = $qq[2] = 3
lizheming
2013-09-08 12:15:09 +08:00
bombless
2013-09-08 13:25:50 +08:00
引用的问题。一个很常见的坑。

前一个foreach的最后一个循环使得$v指向$ww[2],后一个foreach的每一次循环把$qq中的值赋给这里的$ww[2]了
picasso250
2013-09-13 11:12:58 +08:00
楼主试试以下几种情况,及其区别。

1. 原来的这种
foreach ($ww as &$v) {}
foreach ($qq as $v) {}

2. 只需要改个名字,bug就没有了
foreach ($ww as &$vv) {}
foreach ($qq as $v) {}

3. 换个顺序也可以哦
foreach ($qq as $v) {}
foreach ($ww as &$v) {}

4. 其实去掉引用符号就可以了
foreach ($ww as $v) {}
foreach ($qq as $v) {}

5. 当然,官方一点的做法是
foreach ($ww as &$v) {}
unset($v)
foreach ($qq as $v) {}

请对照这些,实验,并且思考。直到自己领悟。

(实话说吧,楼主的当务之急是学英语,学好了英语,这些问题的答案都在php官方手册上摆着呢)
ovear
2013-09-14 14:37:05 +08:00
@picasso250 =。=英文我倒是没问题,但是搜索引擎用的是中文。英文搜索的关键词完全不会。
官方文档是个好东西,之前还没搜到。。
ovear
2013-09-14 14:39:15 +08:00
@anewg TAT,我之前看到了。。就直接感谢了回复者。。V2EX问题解决后需要回复还是关贴?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/81686

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX