百度空间 | 百度首页 
 
查看文章
 
foreach在引用时的陷阱
2008年03月29日 星期六 下午 10:50
作者:老王

这个陷阱在PHP里存在很久了,先看代码:

<?php
$array
= array(1, 2, 3);

foreach (
$array as &$v) {}
foreach (
$array as  $v) {}

print_r($array);
?>


运行代码,得到的结果却是:
Array
(
[0] => 1
[1] => 2
[2] => 2
)
可以发现,经过两次foreach后,最后一个元素由3变成了2。

为什么会这样呢?这是因为第一次foreach的时候$v成为了一个引用变量($array[2]),如此,当第二次foreach的时候,实际上只是在对这个引用变量($array[2])进行了若干次赋值而已。

第一次:$array[2] = 1,此时$array各元素分别为1,2,1
第二次:$array[2] = 2,此时$array各元素分别为1,22
第二次:$array[2] = 2,此时$array各元素分别为1,2,2

一不小心很可能会掉入这个陷阱,为了避免这个问题,需要在第一次foreach后执行unset($v),解决方案有点丑陋,但也没有办法,PHP脚本里的变量一旦生成就在整个脚本中有效,不像Java中,变量是块级别的,仅仅在对应的{}中有效。

PHP的Bug系统里能看到关于这个这个问题的链接,不过从04年提出这个问题到现在已经四年了,估计PHP团队不会解决这个问题了。也是,从PHP的脚本特性来说这也可以说不是Bug,只是苦了我们这些程序员,要多加小心了。

类别:Php | | 添加到搜藏 | 分享到i贴吧 | 浏览() | 评论 (22)
 
网友评论:
1
2008年03月31日 星期一 上午 10:09 | 回复
我从来不在foreach表达式里做引用,我总感觉很别扭,也不明白为什么有很多人要这样做,如果我想使用引用的话,我会首先对整个数组引用后在进行下一步,如:$ref =& $array; foreach($ref as $val)...
 
2
2008年03月31日 星期一 上午 10:40 | 回复
或者这样也行 foreach ($array as $val) { $ref =& $val; }
 
3
2008年03月31日 星期一 下午 04:38 | 回复
如果两个都用&,就还是123 123呢?
 
4
2008年04月01日 星期二 上午 08:43 | 回复
To qinyf:如果两次都是引用,那么赋值赋的也是引用: 第一次foreach后,$v成为$array[2]的引用。 第二次foreach时,依次赋引用值,$v不再只是$array[2]的引用,而依次是$array[0],$array[1],$array[2]。 所以没有变化。
 
5
2008年04月01日 星期二 上午 10:30 | 回复
好久不来了,收藏了。呵呵
 
6
2008年04月01日 星期二 下午 06:16 | 回复
嗯,的确是这样的,我也来说一个吧: $i = "123teset"; $j = (int)'123'; var_dump($i); var_dump($j); if($i == $j) { echo "yes"; }else{ echo "no"; } PHP若类型的陷阱.
 
7
2008年04月01日 星期二 下午 09:43 | 回复
To henry:这算陷阱么?!
 
8
2008年04月03日 星期四 上午 11:06 | 回复
本来以为php5引入foreach的引用是个好事, 哈哈,原来还有这个问题啊
 
9
2008年04月06日 星期日 下午 07:50 | 回复
http://www.phpguru.org/article.php/218
 
10
2008年04月06日 星期日 下午 07:58 | 回复
http://www.corephp.co.uk/
 
11
2008年04月06日 星期日 下午 07:59 | 回复
http://pookey.co.uk/blog/
 
12
2008年04月06日 星期日 下午 08:04 | 回复
http://www.dezinerfolio.com/
 
13
2008年04月07日 星期一 上午 08:42 | 回复
http://code.google.com/p/phaux/
 
14
2008年04月07日 星期一 上午 08:50 | 回复
application business persistence presentation
 
15
2008年04月07日 星期一 下午 02:07 | 回复
http://www.shubulo.com/forum-9-1.html
 
16
2008年04月08日 星期二 上午 08:57 | 回复
http://krumo.sourceforge.net/
 
17
2008年04月08日 星期二 上午 09:06 | 回复
http://tech.groups.yahoo.com/group/domaindrivendesign/
 
19
2008年04月18日 星期五 下午 12:05 | 回复
这个很正常,我常这么用。注意的好,问题还是很容易避免的,想想Javascript把,那个你都能忍受,PHP这样还是可以忍受的。
 
20
2008年04月18日 星期五 下午 12:34 | 回复
http://bbs.chinaunix.net/thread-1081663-1-1.html
 
21
2008年05月23日 星期五 上午 10:52 | 回复
trooman的留言很奇怪,foreach中使用引用就是为了影响array中的值,你写的例子引用起什么用啊。
 
22
2008年11月05日 星期三 下午 02:27 | 回复
不错,呵呵,谢了~
 
23
2010年01月17日 星期日 下午 11:18 | 回复
回复trooman:你这个引用根本是改变临时变量,并没有改变实际的值。
 
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码: 请点击后输入四位验证码,字母不区分大小写
      

     

©2010 Baidu