使用 foreach 使用引用變數需要注意的問題

MArtian發表於2021-06-09

先看程式碼

$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 協議》,轉載必須註明作者和本文連結

相關文章