PHP 引用不是 C 指針。它是符號表別名:兩個變量名指向同一內容(內存地址)。修改任一變量,另一個同步變化。
$a = 'ABC';
$b = &$a; // $b 是 $a 的別名
echo $a; // ABC
echo $b; // ABC
$b = 'EFG';
echo $a; // EFG (受影響)
echo $b; // EFG
function add100(&$num) {
$num += 100;
}
$val = 1;
add100($val);
echo $val; // 101
// 錯誤:add100(1); // 無法將字面量傳引用
function &getStatic() {
static $counter = 0;
$counter++;
return $counter;
}
$a = getStatic(); // 1 (值傳遞)
$a = 5;
$a = getStatic(); // 2 (值傳遞,靜態變量繼續增長)
$a = &getStatic(); // 3 (引用返回,$a 與靜態變量綁定)
$a = 5; // 靜態變量變為 5
$a = getStatic(); // 6
規則:只有 $a = &func() 才建立引用綁定;$a = func() 只是值賦值。
class A { public $abc = 'ABC'; }
$b = new A();
$c = $b; // PHP 5+ 默認對象賦值即引用
$b->abc = 'DEF';
echo $c->abc; // DEF
// 若需副本,使用 clone
$d = clone $b;
$b->abc = 'GHI';
echo $d->abc; // DEF (不受影響)
$a = 1;
$b = &$a;
unset($a); // 僅斷開 $a 與內容的綁定,$b 仍可訪問內容
global $var; // 等價於 $var = &$GLOBALS['var'];
unset($var); // 不會銷毀全局變量
PHP 內核採用 COW 機制:
$a = 'ABC';
$b = $a; // 此時 $a、$b 指向同一內存,無複製開銷
$a = 'EFG'; // 發生寫入,Zend 引擎為 $b 複製一份原數據
這意味著未修改時引用不增加內存,大數組傳遞建議用引用(&$arr)節省內存;但對象默認已是引用語義,無需額外 &。
& 避免複製。&,PHP 5+ 默認引用語義。unset 不再使用的引用變量,釋放符號表條目。