PHP循环引用会遇到的坑

今天遇到这样一个问题:

如果foreach循环一个数组,引用去对它的元素做一些操作,会有什么问题吗?
比如 [1, 2, 3],foreach循环的时候,引用给每个元素 * 2,再去foreach输出,结果会是怎么样的?

先上代码,你可以先猜下会输出什么哦:

<?php
    $arr = [1, 2, 3];
    foreach ($arr as &$v) {
        echo $v * 2;
        echo "<br>";
    }
    var_dump($arr);
    foreach ($arr as $v) {
        echo $v * 2;
        echo "<br>";
    }
    var_dump($arr);

有没有和我一样以为两次输出都是2 4 6的?事实上,结果如下:

2
4
6
array(3) { [0]=> int(1) [1]=> int(2) [2]=> &int(3) } 
2
4
4
array(3) { [0]=> int(1) [1]=> int(2) [2]=> &int(2) }

惊不惊喜意不意外?🤔

这是因为 foreach 循环时,会将当前元素赋值给 $v 变量,然后进入循环体;
foreach 遍历完成后, $v 变量没有释放,而是指向了 arr 数组中的最后一个元素;
所以在后面给 $v 赋值时, 其实改变的是 arr 数组的最后一个元素,所以是最后一个元素一直在引用赋值。

第一个 foreach 循环后,$v 是指向数组的最后一个元素的, 此时 $v 是 2。
在第二个 foreach 循环里可以 var_dump($arr) 输出数组看一下变化,可以推断遍历过程:

array(3) { [0]=> int(1) [1]=> int(2) [2]=> &int(1) } 
array(3) { [0]=> int(1) [1]=> int(2) [2]=> &int(2) } 
array(3) { [0]=> int(1) [1]=> int(2) [2]=> &int(2) }

第一次遍历, 将 arr[0] 赋值给 $v, 相当于 arr[2]=arr[0], 此时 arr 为: [1, 2, 1]
第二次遍历, 将 arr[1] 赋值给 $v, 相当于 arr[2]=arr[1], 此时 arr 为: [1, 2, 2]
第三次遍历, 将 arr[2] 赋值给 $v, 相当于 arr[2]=arr[2], 此时 arr 为: [1, 2, 2]

要想不踩这坑,该怎么办呢?注意变量的声明!前后尽量不要用一样的变量名!

posted @ 2020-05-08 22:38  鹿呦呦  阅读(731)  评论(3编辑  收藏  举报