標籤:
對象記憶體模型
C#的對象記憶體模型
寫這篇部落格的主要目的是為了加深自己的理解,如有不對的地方,請各位見諒。
C#的對象記憶體模型:
一、棧記憶體和堆記憶體
1、棧記憶體
由編譯器自動分配和釋放,主要用來儲存一些局部變數、函數的參數等,例如,int a = 10 ,那麼編譯器會自動在棧上開闢一塊內容用來儲存變數a。
2、堆記憶體
由程式員手動申請和釋放,在C++中,通過new關鍵字申請,編譯器不會釋放,必須通過delete釋放,對於C#,通過new 關鍵字申請,因為編譯器的記憶體回收機制,程式員不需要手動釋放記憶體。例如,我們為類student聲明了一個對象zhangsan,student zhangsan = new student(),首先,編譯器會分配一塊棧上的記憶體儲存變數zhangsan,然後在堆上開闢一塊記憶體來儲存student對象,最後把堆上的地址儲存到變數zhangsan中,如果我們又建立了一個對象lisi,student lisi= new student(),然後lisi = zhangsan,其實更改的只是儲存在棧上的lisi的值,即所指向的對象在堆上的地址,如所示:
3、棧記憶體和堆記憶體的比較
記憶體配置
棧:後進先出式,由編譯器自動分配相應類型的大小,分配的大小受限於棧的大小;
堆:隨意分配,由程式員手動申請指定大小,分配的大小受限於虛擬記憶體。
效率
棧:高
堆:相對棧低
二、實值型別和參考型別
1、實值型別
實值型別變數儲存的是變數的值,直接儲存在棧記憶體中;
2、參考型別
參考型別變數儲存的是變數所在的記憶體的地址,參考型別變數的實際資料存放區在堆記憶體中,變數本身儲存在棧記憶體中,儲存的是指向堆的地址,通常是四個位元組,儲存著一個地址數值。
C#中的實值型別:struct,enum(對於int,float類型,都屬於struct類型)
參考型別:class,delegate,array,interface
具體如所示:
三、深拷貝和淺拷貝
我們在編程中常常會遇到這種問題,我們已經有了一個對象a,並且對象a已經有了一些具體的值,現在我們想建立一個a的副本即對象b,我們希望,操作對象b的同時不改變對象a的值,也就是說對象a和對象b是兩個完全獨立的對象,這即是深拷貝。深拷貝的概念:來源物件與拷貝對象互相獨立,其中任何一個對象的改動都不會對另外一個對象造成影響。
當兩個對象指向同一個地址時,如果我們改變其中一個對象的值,另一個對象也被相應的改變,這即是淺拷貝。淺拷貝的概念:淺拷貝時兩個對象並未完全“分離”,改變頂級對象的內容,不會對另一個對象產生影響,但改變子物件的內容,則兩個對象同時被改變。
這種差異的產生,即是取決於拷貝子物件時複製記憶體還是複製指標。深拷貝為子物件重新分配了一段記憶體空間,並複製其中的內容;淺拷貝僅僅將指標指向原來的子物件。
一些需要注意的東西
(1):String字串對象是引用對象,但是很特殊,它表現的如值對象一樣,即對它進行賦值,分割,合并,並不是對原有的字串進行操作,而是返回一個新的字串對象
(2):Array數組對象是引用對象,在進行賦值的時候,實際上返回的是來源物件的另一份引用而已;因此如果要對數組對象進行真正的複製(深拷貝),那麼需要建立一份數組對象,然後將源數組的值逐一拷貝到目的對象中
(轉)c#對象記憶體模型