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

PHP 參考(&) 深度解析:變數、函式、物件與寫時複製機制

     編輯:PHP 相關知識

PHP 參考(Reference)讓多個名稱指向同一份記憶體內容,但與 C 指標本質不同。本文系統整理 8 大使用場景,並深入剖析 Zend 引擎的「寫時複製」優化機制。

1. 變數參考:別名綁定

<?php
$a = 'ABC';
$b = &$a;   // $b 成為 $a 別名
$b = 'EFG';
echo $a; // EFG($a 同步改變)
?>

2. 函式參考傳遞:修改呼叫端變數

<?php
function add100(&$n) { $n += 100; }
$b = 1;
add100($b);
echo $b; // 101

// 注意:呼叫時不加 &,PHP 5.3+ 已棄用 call-time pass-by-reference
// call_user_func_array 需顯式傳參考
call_user_func_array('add100', [&$b]);
?>

3. 函式參考回傳:回傳變數別名而非值

<?php
function &getCounter() {
    static $c = 0;
    return $c++;
}
$a = getCounter();   // 普通賦值,得到 0
$a = 5;              // 不影響靜態 $c
$a = &getCounter();  // 參考回傳,$a 與 $c 綁定
$a = 5;              // $c 變為 5
?>

實務上常用於物件方法回傳內部屬性參考,如 public function &getData() { return $this->data; }。

4. 物件參考:PHP 5+ 預設行為

<?php
class A { public $v = 'ABC'; }
$b = new A;
$c = $b;        // PHP 5+ 此處為參考複製(handle 複製)
$b->v = 'DEF';
echo $c->v;     // DEF

// 若需真正獨立副本,請用 clone
$d = clone $b;
$b->v = 'GHI';
echo $d->v;     // DEF(不受影響)
?>

PHP 4 需用 $b =& new A 才達到相同效果;PHP 5 new 自動回傳參考,=& 會觸發 E_STRICT。

5. 何時使用參考?效能權衡

  • 大型陣列傳遞:唯讀時不要加 &,Zend 引擎「寫時複製」會自動共享記憶體;只有函式內會修改陣列時才加 &,否則反而觸發複製、降低效能。
  • 物件:預設即為參考行為,無需額外 &。
  • 手動釋放:大型物件/陣列用完可 $var = null 解除綁定,配合 GC 回收。

6. 取消參考 unset()

unset($a) 僅切斷 $a 與內容的綁定,內容本身若仍有其他參考(如 $b)則不會銷毀。

7. global 與 $GLOBALS 參考關係

<?php
$var = 'global';
function test() {
    global $var;           // 等同 $var =& $GLOBALS['var']
    $var = 'changed';      // 影響全域
}
test();
echo $var; // changed
?>

函式內 global $var; $var =& $local; 只改變區域綁定,不影響全域;若要影響全域請用 $GLOBALS['var'] =& $local;。

8. 寫時複製(Copy-on-Write)核心機制

<?php
$a = range('a', 'z'); // 大陣列
$b = $a;              // 此時 $a、$b 指向同一記憶體(zval 引用計數 +1)

function readOnly($arr) { echo count($arr); }
readOnly($a);         // 唯讀傳值 → 無複製,極快

function modify(&$arr) { $arr[] = 'new'; }
modify($a);           // 參考傳遞 → 函式可能寫入 → Zend 為 $b 複製一份
?>

結論:錯誤濫用 & 反而導致不必要的記憶體複製,效能下降 30%+。預設傳值、唯讀場景不加 &、需修改原變數時才加,是最佳實踐。

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