1. 程式人生 > >PHP物件型別在記憶體中的分配

PHP物件型別在記憶體中的分配

  對像型別在PHP 裡面和整型、浮點型、字串型一樣,也是一種資料型別,都是儲存不同型別資料用的, 在執行的時候都要載入到記憶體中去用,那麼物件在記憶體裡面是怎麼體現的呢?記憶體從邏輯上說大體上分為4 段:棧空間段、堆空間段、程式碼段、初始化靜態段,程式裡面不同的宣告放在不同的記憶體段裡面,程式中不同型別資料的宣告將會被存放在不同的記憶體段裡。每段記憶體的特點如下。 
  
1.棧空間段(棧記憶體)
  棧(stack)的特點是空間小但被CPU訪問的速度快,是使用者存放程式中臨時建立的變數。由於棧的後進先出特點,所以棧特別方便用來儲存和恢復呼叫現場。從這個意義上講,我們可以把堆疊看成一個臨時資料寄存、交換的記憶體區。用於儲存佔用空間長度不變且佔用空間小的資料型別的記憶體段,例如整型1、100、100000等在記憶體中佔用空間是等長的,佔用的空間都是32位4個位元組。還有double、boolean等都可以儲存在棧空間段中。
  
2.堆空間段(堆記憶體)


  堆(heap)是用來存放程序執行中被動態分配的記憶體段,它的大小並不固定,可動態擴張或縮減。用於儲存資料長度可變或佔用記憶體比較大的資料。例如,字串、陣列和物件就儲存在這段記憶體中。

3.資料段
  資料段(data segment)通常是指用來存放程式中已初始化且不為0的全域性變數,如:靜態變數和常量。
  
4.程式碼段
  程式碼段(code segment / text segment)通常是指用來存放程式執行程式碼的一塊記憶體區域,比如函式和方法。程式碼段需要防止在執行時被非法修改,所以只准讀取操作,而不允許寫入(修改)操作。

這裡寫圖片描述

  物件型別的資料就是一種佔用空間比較大的資料型別,並且是佔用的空間不定長的資料型別,所以物件建立完成以後被存放在堆記憶體中,但物件的引用名稱是存放在棧裡面的。程式在執行時,棧記憶體中的資料是可以直接存取的,而堆記憶體是不可以直接存取的記憶體。但可以通過物件的引用名稱來訪問物件中的成員,即通過物件名稱使用物件。
這裡通過Person類例項化的三個物件使用圖形,來說明物件型別的資料是如何在記憶體中儲存的。

這裡寫圖片描述

   從上圖可以看出$p1=new Person();等號右邊是真正的物件例項,在堆記憶體裡面的實體,而等號右邊則是物件的引用,儲存在棧記憶體段中。

  在PHP中,只要使用一個new這個關鍵字,就會例項化出來一個物件,並在堆裡面開闢一塊自己的空間。上圖一共有3次new Person(),所以會在堆裡面開闢3 個空間,產生3 個例項物件,每個物件之間都是相互獨立的,使用自己的空間。
  在記憶體中,儲存資料的每個空間都有獨立的記憶體地址,記憶體的地址通常是使用十六進位制數表示,物件中的每個成員在堆記憶體中儲存時都會有一個地址。
  每個在堆裡面的例項物件是儲存屬性的,比如說,現在堆裡面的例項物件裡面都存有姓 名、性別和年齡。每個屬性又都有一個地址。 $

p1=new Person();等號的右邊$p1 是一個引用變數,通過賦值運算子“=”把物件的首地址 賦給“$p1”這個引用變數,所以$p1 是儲存物件首地址的變數,$p1 放在棧記憶體裡邊,$p1 相當 於一個指標指向堆裡面的物件,所以我們可以通過$p1 這個引用變數來操作物件,通常我們也 稱物件引用為物件。 如上圖,第一個物件的首地址為“0xff001”,如果在程式中知道記憶體的首地址,就會按順序找到物件中的每個成員。而在“$person1=new Person();” 語句中,通過賦值運算子“=”把第一個物件在堆記憶體中的首地址“0xff001”賦給了變數$person1,所以等號左邊的$person1就是第一個物件的引用變數。變數$person1存放的是一個十六進位制整數,被存放在棧記憶體中。$person1是一個儲存地址的變數,相當於一個指標指向堆裡面的物件。所以訪問第一個物件中的每個成員都要通過這個引用變數$person1來完成,通常也可以吧物件引用當成物件來看待。同樣,第二個物件的首地址“0xff002”賦給棧裡面的引用變數“$person2”,通過這個引用變數訪問第二個物件中的每個成員。以此類推。