这道经典PHP面试题有点不懂

<?php
   //第2题:
    $arr = [1,2,3];
    foreach($arr as &$v) {
        //nothing todo.
    }
    foreach($arr as $v) {
        //nothing todo.
    }
    var_export($arr);
    //output:array(0=>1,1=>2,2=>2),你的答案对了吗?为什么
?>

作者:舒铭 链接:https://zhuanlan.zhihu.com/p/... 来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

请问为什么是这样呢?

阅读 6.6k
评论
    7 个回答

    foreach的问题,参考:
    http://php.net/manual/en/cont...

    标准的写法:在使用了“ & ”的 foreach 之后,需要写一句 unset($v); 释放掉临时的引用。

    该题的两个foreach的代码效果类似于以下代码:

    $v = &$arr[0];
    $v = &$arr[1];
    $v = &$arr[2];
    //var_dump($arr);
    
    //请注意,从这个时候开始,$v和$arr[2]是等价的
    
    $v = $arr[0];
    $v = $arr[1];
    $v = $arr[2];
    //var_dump($arr);
    

    这个面试题应该就是考察PHP的代码规范了,毕竟这种细节很容易被忽略,有时候确实会导致问题。

      原因就是在第一次遍历时用的是&val引用赋值,而在foreach完之后,这个$val依然存在,是$arr[2]元素的引用
      当进入到第二次遍历时,在遍历到第一个元素时$val被赋值为1,相当于

      $arr[2] = 1;

      遍历到第二个元素时

      $arr[2] = 2;

      遍历到第三个元素时

      $arr[2] = $arr[2]

      所以最后的结果就成了1,2,2。

        • 5.1k

        这个问题我在本站曾多次回答,如果你曾百度就能解决,没必要发布一个问题的。
        这个问题的根本原因在于
        php是没有块级作用域的!!

        答案

        php是没有块级作用域的!!!
        也就是说,第一个循环结束后,$item依然指向数组的第三个成员。
        之后每次循环,就把数组的第一个值写到第三个成员,然后是第二个值写个第三个成员,然后是第三个值写到第三个成员,但此时第三个值已经被上次修改成2了,所以这次第三个值会被修改成2.

        证明

        这里。我们将这个代码修改一下,加点调试信息

        $a = array(1,2,3);
        foreach($a as &$item){
            echo $item . ',';
        }
        var_dump($a);
        foreach($a as $item){
            var_dump($a);
            echo $item . ',';
        }

        上述程序输出结果为

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

        你看明白了吗?

          没怎么学过PHP,大体猜测。

          第一个foreach是引用赋值,第一个循环结束后$v指向数组的第三个元素。

          也就是说$v等同于$arr[2]。

          然后在第二个循环里给$v赋值。第一次后数组变成[1,2,1],第二次变成[1,2,2]第三次$v = $arr[2],也就是自身赋值给自身,所以最后为[1,2,2]。

              如果php有块级作用域就没啥问题了

                • 9.3k

                哈哈,好问题~

                  撰写回答

                  登录后参与交流、获取后续更新提醒