百度首页 | 百度空间
 
查看文章
 
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 | 添加到搜藏 | 浏览() | 评论 (21)
 
最近读者:
 
网友评论:
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
<?php
$array = array(1, 2, 3);

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

print_r($array);
?>

如果两个都用&,就还是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/
 
18
2008年04月11日 星期五 上午 09:11
presentation
application
domain: model(entity, value object), service, repository, factory
persistence
 
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中的值,你写的例子引用起什么用啊。
 
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码:
 

     

©2008 Baidu