延續上篇 zval 結構介紹,本文透過符號表與 zval 互動,圖解引用計數、引用傳參、引用返回、global 關鍵字、foreach 引用副作用等核心機制。
active_symbol_table 指向當前作用域符號表。refcount__gc 記錄指向該 zval 的變數數量;is_ref__gc 標記是否為引用集合。refcount++;修改時才分離複製。$a = $b → 符號表 a,b 指向同一 zval,refcount=2, is_ref=0。$b = &$a → 同一 zval,is_ref=1,修改任一變數影響另一個。refcount++;函數內修改觸發 COW 分離。function(&$s) → 形參標記 is_ref=1,修改直接影響外部變數。function &find() 將內部變數 zval 綁定給呼叫端變數,達成跨作用域引用。is_ref=1)。unset 只解除局部綁定。$a = [1,2,3];
foreach ($a as &$v) { $v *= $v; } // $v 成為 $a[2] 的引用
foreach ($a as $v) { echo $v; } // 第二輪以值複製,但 $v 仍是引用,導致 $a[2] 被覆寫
// 輸出:1 4 4 (非預期 1 4 9)
解決:第一個 foreach 結束後 unset($v) 解除引用。
$a = 123;
xdebug_debug_zval('a');
$b = &$a;
xdebug_debug_zval('a'); // 觀察 refcount/is_ref 變化
理解符號表與 zval 互動,即能掌握 PHP 變數行為本質,避免常見引用陷阱。