首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP foreach 參考迭代後的殘留引用陷阱:為什麼陣列最後一個元素會被竄改?

     編輯:PHP 綜合知識

現象重現

<?php
$ar = [1, 2, 3];
var_dump($ar);
foreach ($ar as &$v) {}  // 參考迭代
foreach ($ar as $v) {}   // 一般值迭代
var_dump($ar);
/*
輸出:
array(3) { [0]=>1 [1]=>2 [2]=>3 }
array(3) { [0]=>1 [1]=>2 [2]=>&int(2) }  // 最後一元素變成 2!
*/
?>

明明第二個 foreach 沒有任何賦值操作,陣列最後一元素卻被改成倒數第二元素的值。

根因分析

  1. 第一個 foreach ($ar as &$v) 結束時,$v 仍保持對 $ar[2] 的參考。
  2. 第二個 foreach ($ar as $v) 採用值複製模式。PHP 為了效能,重複使用同一個變數符號 $v,而非建立新變數。
  3. 當第二個循環處理第一個元素 $ar[0] 時,執行「將 $ar[0] 的值賦值給 $v」。此時 $v 仍是指向 $ar[2] 的參考,導致 $ar[2] = $ar[0]。
  4. 後續循環同理,最終 $ar[2] 變成 $ar[1] 的值(倒數第二元素)。

這不是 Bug,而是 PHP 變數作用域與參考機制的語言特性。官方文件已以 Warning 標註。

解決方案:unset 斷開引用

<?php
$ar = [1, 2, 3];
foreach ($ar as &$v) {}
unset($v);          // 關鍵:銷毀參考變數,後續 $v 將重新綁定
foreach ($ar as $v) {}
var_dump($ar);      // 正常輸出 1, 2, 3
?>

最佳實踐建議

  • 習慣: 使用參考迭代 foreach ($arr as &$v) 後,立即 unset($v)。
  • 替代: 若需修改原陣列,改用 foreach ($arr as $k => $v) { $arr[$k] = ...; } 避免參考殘留。
  • PHP 7.0+ 仍保留此行為,未來版本也極難改變(會破壞向後相容)。

參考資料

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved