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

深入理解 PHP 變數:值類型 vs 引用類型與 & 符號機制

     編輯:PHP 綜合知識

PHP 變數底層儲存的是「指向值的地址」,而非值本身。理解這一點,才能徹底搞懂值傳遞、引用傳遞(&)、物件複製與複製行為的本質區別。

變數儲存模型

$a = 1;
// 實際過程:
// 1. 解析器在記憶體分配空間存放整數 1
// 2. 將該記憶體地址存入變數 $a 的符號表條目
// 3. 讀取 $a 時:查符號表 → 取地址 → 讀記憶體值 → 輸出

引用賦值(&):共享同一記憶體地址

$a = 1;
$b = &$a;  // $b 存入 $a 的地址,非複製值

echo $b; // 1
$a = 2;
echo $b; // 2  ← 改變 $a,$b 同步變化
$b = 3;
echo $a; // 3  ← 雙向綁定

結論:$a 與 $b 指向同一記憶體位址,是同一個變數的不同別名。

值賦值(預設):複製地址指向新值(寫時複製)

$a = 1;
$b = $a;  // 複製 $a 的地址,但 PHP 採用 COW 機制
$a = 2;
echo $b; // 1  ← $b 仍指向舊值 1

標量(整數、浮點、字串、布林)、陣列在賦值時觸發 Copy-on-Write:實際複製發生在「任一變數被修改」時刻,而非賦值瞬間。

物件:預設即引用行為

class User { public $name = 'Tom'; }
$a = new User;
$b = $a;        // 未用 &,但物件標識符被複製
$a->name = 'Jim';
echo $b->name; // Jim  ← 兩變數指向同一物件實例

關鍵區別:物件變數存的是「物件標識符」,賦值複製的是標識符,故指向同一實例。若需獨立副本,必須用 clone:

$b = clone $a; // 建立新實例,屬性淺拷貝
$a->name = 'Tom';
echo $b->name; // Jim

函數參數傳遞

宣告呼叫行為
function f($x)f($a)值傳遞(標量/陣列 COW,物件共享實例)
function f(&$x)f($a)引用傳遞,函數內修改影響外部變數
function f(User $x)f($a)型別宣告,仍屬值傳遞(複製物件標識符)

常見陷阱與最佳實踐

  1. foreach 迴圈引用殘留:
    foreach ($arr as &$v) { $v *= 2; }
    unset($v); // 必須 unset,否則 $v 仍引用最後一個元素
  2. 函數返回引用:function &f() { return $globalVar; } 僅在需「修改返回值」時使用(如鏈式賦值),濫用降低可讀性
  3. 陣列複製性能:大陣列頻繁複製會觸發 COW 實際拷貝,考慮傳引用或使用 ArrayObject/Generator
  4. 物件不可變模式:若不想外部修改內部狀態,回傳 clone 或 readonly 屬性(PHP 8.1+)

總結對照表

類型賦值 $b=$a引用 $b=&$a函數傳值函數傳引用
標量/字串COW 獨立共享COW共享
陣列COW 獨立共享COW共享
物件共享實例共享變數槽共享實例共享變數槽
資源共享資源 ID共享變數槽共享資源 ID共享變數槽

掌握「地址、COW、物件標識符」三大核心概念,即可精準預測 PHP 變數在任何情境下的行為。

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