lovecn / lovecn.github.io

个人记录
5 stars 5 forks source link

php引用foreach输出问题 #21

Open lovecn opened 9 years ago

lovecn commented 9 years ago

$arr = array('1','2'); foreach($arr as &$value){ } foreach($arr as $value){ var_dump($value); } 输出 string(1) "1" string(1) "1" 谁给解释一下?

foreach($arr as &$value) { //noop } 大致是

begin first foreach

$value = &$arr[0]; //noop $value = &$arr[1]; //noop

end foreach

这时候如果打印$arr,你会看到

array(2) { [0]=> string(1) "1" [1]=> &string(1) "2" } 也就是说$value仍然是$arr[1]的引用(别名)

然后我们再把第二个foreach拆开

begin second foreach

$value = $arr[0];//note: 由于$value <=> &$arr[1], 此时$arr[1]被赋值成为$arr[0],也就是1

var_dump($value);//1

$value = $arr[1];//相当于$arr[1] = $arr[1]; 没有实际效果

var_dump($value);//1

end foreach

解决方案是永远不要用&

或者老老实实按照官网的指示,用unset解除引用

<?php $arr = array(1, 2, 3, 4); foreach ($arr as &$value) { $value = $value * 2; } // $arr is now array(2, 4, 6, 8) unset($value); // break the reference with the last element ?>

简单点来说。 第一个foreach结束后,$value = &$arr[1],注意,这里是引用,可以理解为指针 重点在第二个foreach: 第一次是&$arr[1] = $arr[0],这个是赋值操作,这个时候$arr[1]的值已经已经被修改为$arr[0]了,也就是1.此时$arr = ['0'=>1,'1'=>1]. 第二次&$arr[1] = $arr[1],同上.最终$arr = ['0'=>1,'1'=>1].

$value 和 $arr[1] 指向同一个内存空间了,第二个循环每次循环实际上改的都是$arr[1]的值 mcfog 解释很详细。就是在第一次循环中 value实际上一直作为 $arr[$i]的引用,那么循环结束后,$value 就是 $arr[1] 的引用,$value 和 $arr[1] 指向同一个内存空间。第二个循环每次循环给$value 赋值的时候 实际上改的都是$arr[1]的值