foreach引用坑
先看下面代码
$arr1 = [1, 2]; foreach($arr1 as $key => $value) { $value = $value + 1; } var_dump($key, $value); //结果输出1,3
说明:在上面的foreach循环中,当循环结束后,临时变量 $key和$value变量都不会被自动释放掉。值会被保存下来。而且此时修改$val的值不会影响$arr。
理解foreach的原理,对上面的结果不难理解,foreach循环时,每次循环就会把`$arr1`元素的值复制给临时变量:$key, $value。如,第一次循环时,如下
$key = 0; $value = $arr1[0];
第二次循环时,如下
$key = 1; $value = $arr1[1];
再看forach中使用引用
引用:如果想在遍历数组的过程中修改数组的元素,可以在foreach中对$val使用引用。此时被引用的元素$val指向当前数组元素的内存地址,即共享一段内存地址。因此修改$val的值会同时改变$arr[$key]的值。
$arr1 = [1, 2]; foreach($arr1 as $key => $value) { $value = $value + 1; } var_dump($key, $value); //结果输出1,3
var_dump($arr1);
$arr1 的值 为 ['0' => 2, '1' => 3]
说明:$key , $value 的值和上面的非引用情况下一样。在foreach中使用&引用后,当foreach结束后,$key和$val变量也都不会被自动释放掉,但是此时$val和$arrcount($arr) - 1指向相同的内存地址。因此,此时修改$val的值也会改变了$arr[3]的值。
foreach 引用时,原理和上面一样,只不过是引用复制,原来如下
第一次循环: $key = 0; $value = &$arr1[0]; 第二次循环: $key = 1; $value = &$arr1[1];
再看个例子:
$arr1 = [1, 2]; foreach($arr1 as $key => &$value) { $value = $value + 1; } var_dump($arr1); $value = 100; var_dump($arr1);
第二次输出 $arr1时,第二个元素的值也是100了。
理解了原理,就知道坑了。如果我们2个foreach循环,使用相同的临时变量就会有问题了,一个foreach在使用引用的时候。
如:
$arr1 = [1, 2]; foreach($arr1 as $key => &$value) { $value = $value + 1; }
//此时 $value = &$arr1[1] ,后面改变$value的值就会改变$arr1[1]元素的值。 $arr2 = [10, 20, 30]; foreach ($arr2 as $value) { var_dump($arr1); }
我们发现在循环$arr2时,$arr2元素复制给$value后,同时$arr1的最后一个元素的值也发生变化,此时等于$arr2此时指针对应元素的值。依次推,$arr1最后一个元素的值 = $arr2元素的最后一个值。
解决方法,使用unset()释放元素, 或者循环第2个数组的时候,使用不同的临时变量
$arr1 = [1, 2]; foreach($arr1 as $key => &$value) { $value = $value + 1; } unset($value); $arr2 = [10, 20, 30]; foreach ($arr2 as $value) { var_dump($arr1); }