使用 foreach 使用引用变量需要注意的问题

先看代码

$arr = [1, 2, 3];
foreach($arr as &$value){

}

foreach($arr as $value){

}

print_r($arr);

// 预期
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
)

// 实际
Array
(
    [0] => 1
    [1] => 2
    [2] => 2
)

foreach 在执行的时候,会依次把数组 $arr 键的值赋值给 $value,并且 $value 并不是局部变量,它存在于全局中。


所以在第二次 foreach 执行的时候,此时的 $value = &$arr[2],由于它的内存地址指向了 $arr[2],所以在第二次的 foreach 循环中,每一次对 $value 的赋值,其实都是在改变 $arr[2] 的值。

$arr = [1, 2, 3];
foreach($arr as &$value){
    // 第一次循环  $value = &$arr[0];
    // 第二次循环  $value = &$arr[1];
    // 第三次循环  $value = &$arr[2];
}
// 循环结束后由于 $value 处于全局中,它依然指向 $arr[2] 
// 于是:
foreach($arr as $value){
    // 第一次循环 $value = $arr[0];
    // 实际上     $arr[2] = $arr[0];

    // 第二次循环  $value = $arr[1];
    // 实际上     $arr[2] = $arr[1];

    // 第三次循环  $value = $arr[2];
    // 实际上     $arr[2] = $arr[2];
    // 此时 $arr[2] 与 $arr[1] 相等
}

要解决这个问题也很简单

$arr = [1, 2, 3];
foreach($arr as &$value){

}
// 每次循环引用数组值的时候,循环之后要将 $value 释放掉
unset($value);
foreach($arr as $value){

}

print_r($arr);

// 输出
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
) 

这应该是 PHP新手 经常忽略的问题,要记住 foreach 并不像 function 一样产生作用域,他的变量处在全局中。

记录一下。

本作品采用《CC 协议》,转载必须注明作者和本文链接
悲观者永远正确,乐观者永远前行。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
讨论数量: 4
JaguarJack

老生常谈了

3年前 评论
sreio
$arr = [1, 2, 3];
foreach($arr as &$value){

}
foreach($arr as $value1){

}

print_r($arr);

// 输出
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
) 
3年前 评论
sreio (作者) 3年前

感谢了,之前看各种文章还是云里雾里的。看到了文章里面第二个 foreach 的注释秒懂了。 :+1:

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!