一、php的foreach实现比较诡异,是不是先拷贝了?  ----simeng总结的

代码如下:
<?php
$p=array(1,2,3,4,5);
foreach($p as $key => $value)
{             
print_r($value."\n");
$p[$key+1]=5;
}
print_r($p);
?>

输出:
1
2
3
4
5
Array
(
[0] => 1
[1] => 5
[2] => 5
[3] => 5
[4] => 5
[5] => 5
)

simeng的分析:原来php的foreach实现如此诡异。 注: 除非数组是被引用,foreach 所操作的是指定数组的一个拷贝,而不是该数组本身。

总结:如果试图在循环中修改array的某个value的值以影响下次循环的判断,这样会失败。

二、foreach中使用引用传递时注意的问题

代码如下:
<?php
$arr1 = array(1, 2, 3);
$arr2 = array(4, 5, 6);

foreach($arr1 as $key => &value) {
#do something...
}

foreach($arr2 as $key => value) {
#do something...
}

print_r($arr1);
?>

输出结果:
Array
(
[0] => 1
[1] => 2
[2] => 6  #此值被修改
)

原因分析:第一个循环结束后,$value与arr1[2]是同一引用,第二个循环中,每次都会修改arr1[2]的值,最后修改成6。

总结:如果在foreach中使用了&, 需要注意用完后unset($value)一下,或者尽量使用有意义的变量名,避免重复。

三、foreach不使用'&'时的参数传递的问题

对于如下代码:
foreach ($arr as $key => $value) {

#modify the $value;
#eg1: $value = 100; $value = "str";
#eg2: $value[0] = 100;  $value[0][1] = 100;
#eg3: $value->a = 100; $value[0]->setA = 100;
}
对3个示例结果如下:
1. 如果$value是基本数据类型、字符串时,foreach内部的修改是不会影响原有数组的值;
2. 如果$value是基本类型的数组(一维或者多维)时,foreach内部的修改是同样不会影响原有数组的值;
3. 如果$value是自定义的类或者类数组时,foreach内部的修改是会影响原有数组的值。

以上是通过代码验证的结果。

总结:使用foreach且数组中的value不用'&'修饰时,执行前会先copy一份循环数组。
对于基本数据类型和数组,相当于是两份数据,所以不会修改原有数据;
但是对于自定义类,copy属于浅拷贝,只是拷贝了对象的引用值,因此原有对象被修改。

PS:以上都是根据实际代码测试所得结论,如有描述不对的地方欢迎批评指正。

PHP: foreach的几个诡异问题发现与探究
标签: