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

PHP 靜態成員記憶體佈局深度剖析

     編輯:PHP 相關知識

理解 static 成員在記憶體中的真實存放位置,是避免「修改一處、全局生效」等經典 Bug 的關鍵。本文通過 print_r() 實測,直觀展示靜態屬性與實例屬性的本質區別。

核心結論先行

  • 靜態屬性:存儲於「類」的記憶體空間,全進程僅一份,不屬於任何實例。
  • 非靜態屬性:隨每個 new 操作在「物件」記憶體中獨立分配。
  • 所有方法(靜態/非靜態):代碼段同樣存儲於「類」空間,僅有一份拷貝。

實證代碼與輸出分析

<?php
header("content-type:text/html;charset=utf-8");

class Human {
    static public $name = "小妹";
    public $height;
    public function tell() {}
}

echo Human::$name; // ① 類直接訪問,無需實例

$p1 = new Human();
$p2 = new Human();

print_r($p1); 
// 輸出:Human Object ( [height] => )  ← 只有 height,沒有 name!

$p1::$name = "夫人"; // ② 通過物件修改靜態屬性
echo $p2::$name;     // 輸出:夫人  ← p2 也變了!
?>

現象解讀

  1. 類聲明即存在:Human::$name 在腳本加載階段就已分配記憶體,與是否 new 無關。
  2. 物件不包含靜態屬性:print_r($p1) 僅顯示 height,證明 name 不在物件結構體中。
  3. 全局共享單一拷貝:任何途徑(類名、物件1、物件2)修改 $name,影響所有後續讀取。

方法同樣屬於類

無論 static function 還是普通 function,其機器碼都只在類定義時載入一次。new 出來的物件僅持有屬性數據,方法調用通過類的虛函數表分發。這也是為何 print_r($obj) 永遠不會列出方法。

開發啟示

  • 靜態屬性適合「全局單一狀態」(如資料庫連接池、配置快取、單例模式實例)。
  • 切勿將「實例級別狀態」誤設計為靜態,否則多物件場景下會相互污染。
  • 記憶體洩漏風險:靜態屬性持有大型物件引用時,生命周期贯穿整個請求,需手動 unset 或設為 null 釋放。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved