php在foreach中使用引用赋值&详解

本片博文使用的php版本:5.6、7.1


话不多说,直接上代码

$test=array('a','b','c');

foreach($test as &$value)
{
    echo $value;
}
echo $value;

foreach($test as $value)
{
    echo $value;
}
echo $value;

运行结果:

a,b,c

c

a,b,b

b

看到没,是不是很奇怪 第二次foreach的结果为什么不是abc而是abb呢?


解释:  

在第一个foreach中,我们使用了赋值引用符号,它的意思是每次遍历时,$value指向的是$test数组中的对应元素的地址,循环一次时,$value指向的是'a'的地址,第二次循环的时候,$test指向的是第二个元素'b'的地址,第三次循环时,指向的就是'c'的地址。当我们在做第二次foreach遍历的时候,其实$value变量指向的还是$test的第三个元素即'c'的地址。此时$value仍然指向$test数组第2个元素的地址。然后foreach本身的操作是把数组中对应的元素赋值给as后面的变量,所以在第二个foreach中,遍历第一次的时候,把‘a’赋值给$value指向的地址即['a','b','a'],第二次遍历的时候,把'b'赋值给$value指向的地址即['a','b','b'],第三次遍历的时候,就把'b'赋值给$value指向的地址,这也就是为什么输出结果是['a','b','b']而不是['a','b','c']的原因。


通俗易懂一句话 就是 当第二个foreach在循环时实际上是在不停的给$test数组的最后一个元素($test[2])赋值,因为第二次foreach每次产生的$value都是和第一次foreach最后所保留的&$test[2]数组元素共同指向同一块内存地址 所以$value每次产生的值都会同时更改$test[2]元素的值。听懂了吧!!!!!!


第二次foreach具体赋值情况:

第一次:a 赋值给第2个元素,结果为: [a,b,a] 

第二次:b 赋值给第2个元素,结果为: [a,b,b]  

第三次:此时因为第2个元素已经变成b 所以又重新把b赋值给第2个元素,所以最终结果:[a,b,b]

使用&引用符合的时候,一定要及时注意这些小细节问题,不然会产生很多不可思议的bug,这种潜伏的bug还是挺难查找的。那如何让第二次foreach也能输出我们期望的结果a,b,c呢?


解决方案:

1、在使用完赋值引用操作符之后,把变量unset掉,例如在上例中在第一次foreach完毕之后 加上unset($value)语句,即取消$value对$test[2]元素地址的引用,这样第二次foreach的时候,$value相当于新的变量,不会导致上述问题。这也是一个很好的编程习惯。

2、尽量不使用相同的循环变量名。即第二次foreach as的循环变量名为$variable,随便你叫什么都行,只要不和第一次foreach as的循环变量名一样就行!!!!!!

实验:

$test = array('a','b','c');  
  
foreach($test as &$value)
{  
     //对$value进行操作  
}  
var_dump($test);

大家如果运行一下的话,会发现浏览器打印出来的结构是这样的:

array (size=3)
  0 => string 'a' (length=1)
  1 => string 'b' (length=1)
  2 => &string 'c' (length=1)

大家有木有发现,元素'c'的前面有个赋值引用符号'&',原因就在这里。


再看一个例子吧,为了加强理解,加深印象

$arr = array(3, 2, 1);

foreach($arr as &$v)
{

}

foreach($arr as $v)
{

}

var_dump($arr); // 3 2 2

经过上面的解释,不用说也知道输出结果是 3 2 2,那么它的实际执行步骤如下:


第一个foreach循环之后,$v指向得是数组得最后一个元素$v = $arr[2]。而第二个foreach循环

$arr[2] = $v = $arr[0] //3

$arr[2] = $v = $arr[1] //2  特别注意这一步,这一步是影响下一步输出结果的关键一步

$arr[2] = $v = $arr[2] //2  因为此时$arr[2] = 2

所以是 3 2 2,所以理解了吧~


也可以参考下面这两位博主的博文:

http://blog.csdn.net/luan111111/article/details/50420534

http://blog.csdn.net/zhouzme/article/details/52063243


后记:

这些小细节一定要注意了!!!!!!

这些小细节一定要注意了!!!!!!

这些小细节一定要注意了!!!!!!

重要的话说三遍。  今天先到这里  拜~ 


声明:禁止任何非法用途使用,凡因违规使用而引起的任何法律纠纷,本站概不负责。

小周博客
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

精彩评论

全部回复 0人评论 7,777人参与

loading