在 PHP 中,引用意味著不同的變量名稱指向同一個變量內容。這與 C 語言的指標有本質區別:C 指標存儲的是變量在內存中的地址,而 PHP 的引用是符號表層面的別名綁定。理解這一機制對編寫高效、穩定的 PHP 代碼至關重要。
PHP 允許兩個變量指向同一內容。使用 & 符號建立引用關係:
<?php
$a = "ABC";
$b = &$a;
echo $a; // 輸出: ABC
echo $b; // 輸出: ABC
$b = "EFG";
echo $a; // 輸出: EFG (因為 $a 和 $b 指向同一內容)
echo $b; // 輸出: EFG
?>
此時 $a 和 $b 在符號表中指向同一個 zval 結構,修改任一變量都會影響另一個。
函數參數前加 & 可實現傳址調用,函數內部修改參數會影響外部變量:
<?php
function test(&$a) {
$a = $a + 100;
}
$b = 1;
echo $b; // 輸出 1
test($b);
echo "<br>";
echo $b; // 輸出 101
?>
注意:test(1) 這樣直接傳遞字面量會報錯,因為無法對字面量建立引用。
PHP 規定只有使用 $a = &test() 才能獲得函數的引用返回:
<?php
function &test() {
static $b = 0;
$b = $b + 1;
echo $b;
return $b;
}
$a = test(); // 輸出 1,普通調用,$a 只是值拷貝
$a = 5;
$a = test(); // 輸出 2,仍不影響靜態變量 $b
$a = &test(); // 輸出 3,引用返回,$a 與 $b 綁定
$a = 5;
$a = test(); // 輸出 6,$b 的值已被改為 5,再遞增變 6
?>
引用返回的本質是將返回變量的內存地址與接收變量綁定,類似 $a = &$b。此特性常用於物件模式中。
PHP 5 中物件預設以引用方式傳遞和賦值:
<?php
class A {
var $abc = "ABC";
}
$b = new A;
$c = $b; // 相當於 $c = &$b
echo $b->abc; // ABC
echo $c->abc; // ABC
$b->abc = "DEF";
echo $c->abc; // DEF (因為 $b 和 $c 指向同一物件)
?>
若需建立物件副本且不受原物件影響,需使用 __clone 魔術方法實現深拷貝。
& 方式,再用 $var = null 釋放。unset 僅斷開變量名與內容的綁定,不銷毀內容本身:
<?php
$a = 1;
$b = & $a;
unset($a); // $b 仍存在,值為 1
?>
global $var 實際建立到 $GLOBALS["var"] 的引用,unset $var 不會銷毀全局變量。物件方法中 $this 永遠是調用該方法物件的引用。
PHP 內核採用「寫時拷貝」機制:
$a = "ABC"; $b = $a; 此時兩者指向同一內存地址,不佔用額外內存。$a = "EFG"; 發生寫操作,Zend 核心自動為 $b 複製一份數據,重新分配內存。這種機制在不發生寫入時極大節省了內存開銷。