• php foreach变量引用的问题


    PHP中变量的作用域不像java, c中的那样有明确的限定。比如, 我们在一个php文件中有这样一段代码:

    $data = ['a', 'b', 'c'];
    //在foreach循环中建立了变量$key和$value
    foreach ($data as $key => $value) {
        //do nothing here
    }
    //在foreach外面仍然可以访问这两个变量
    var_dump($key);
    var_dump($value);
    

    在这个foreach循环中定义的变量$key$value, 在foreach外面也是可以访问的。上面代码的执行结果是:

    int(2)
    string(1) "c"
    

    当然,如果这个foreach是在一个function内,那么在这个function外是不能直接访问这两个变量的。

    例子

    例1

    看下面这个例子:

    $data = ['a', 'b', 'c'];
    foreach ($data as $key => $value) {
        $value = &$data[$key];//引用
    }
    print_r($data);
    

    执行的结果是:

    Array
    (
        [0] => b
        [1] => c
        [2] => c
    )
    

    我们可以看到变量$data的值已经被改变了! 这很奇怪吧! 我们在循环中打印变量:

    $data = ['a', 'b', 'c'];
    foreach ($data as $key => $value) {
        $value = &$data[$key];//引用
        echo $key, ': ', $value, ' => ', json_encode($data) . PHP_EOL;
    }
    

    执行结果是:

    0: a => ["a","b","c"]
    1: b => ["b","b","c"]
    2: c => ["b","c","c"]
    

    我们可以看到:

    • 第一次循环时
      • 先把$data[0]赋给了变量$value
      • 随后又将变量$value变成了地址引用,指向$data[0]
    • 第二次循环时
      • 先把$data[1]赋给了变量$value,但是因为变量$value是指向$data[0]的,这导致$data[0]的值被修改为 b
      • 随后又将$value指向了$data[1]的地址
    • 第三次循环时
      • 先把$data[2]赋给了变量$value,但是因为变量$value是指向$data[1]的,这导致$data[1]的值被修改为 c
      • 随后又将$value指向了$data[2]的地址

    如果在这个代码后面再修改一下$value的值, 数组$data会变成什么样呢?

    $data = ['a', 'b', 'c'];
    foreach ($data as $key => $value) {
        $value = &$data[$key];//引用
        echo $key, ': ', $value, ' => ', json_encode($data) . PHP_EOL;
    }
    foreach ($data as $key => $value) {
    }
    print_r($data);
    //在这里修改$value的值, 然后在看看原来的数组变成了什么
    $value = 120;
    echo $value . PHP_EOL;
    print_r($data);
    

    执行结果是:

    0: a => ["a","b","c"]
    1: b => ["b","b","c"]
    2: c => ["b","c","c"]
    Array
    (
        [0] => b
        [1] => c
        [2] => c
    )
    120
    Array
    (
        [0] => b
        [1] => c
        [2] => 120
    )
    

    我们可以看到, $data[2]的值变成了120,而这可能不是我们想要的!

    例2

    这是例子是参考手册上的:

    $arr = [1, 2, 3, 4];
    foreach ($arr as &$value) {
        $value = $value * 2;
    }
    echo '$arr 现在是 ' . json_encode($arr) . PHP_EOL;
    // $arr 现在是 [2, 4, 6, 8]
    
    // 前面没有unset掉, 所以这里 $value 仍然指向 $arr[3] 的地址
    foreach ($arr as $key => $value) {
        // $arr[3] 的值会在每一次循环时被修改
        echo $key . ' => ' . $value . '  $arr 现在是 ' . json_encode($arr) . PHP_EOL;
    }
    

    执行结果是:

    $arr 现在是 [2,4,6,8]
    0 => 2  $arr 现在是 [2,4,6,2]
    1 => 4  $arr 现在是 [2,4,6,4]
    2 => 6  $arr 现在是 [2,4,6,6]
    3 => 6  $arr 现在是 [2,4,6,6]
    

    如何避免地址引用带来的问题?

    1. unset()来destroy掉变量
    2. 不用地址引用
  • 相关阅读:
    冯诺依曼体系结构 计算机组成的金字塔
    Vue3生命周期
    【无标题】markdow 模板
    问卷答案的整理
    (保姆级)服务器-Zabbix6.0使用Python脚本实现带图片的邮箱的报警
    【Python基础篇】字符串的拼接
    Windows Server 2012 R2系统远程桌面的数字证书算法SHA1升级到SHA256
    SpringCloud Alibaba——记录一种nacos配置中心动态刷新不起效的解决方式(@ConfigurationProperties)
    12个MySQL慢查询的原因分析
    夜天之书 #90 再谈 Rust 项目社群治理
  • 原文地址:https://blog.csdn.net/aben_sky/article/details/126943849