1. 程式人生 > >C#中的記憶體管理(二)儲存區域劃分

C#中的記憶體管理(二)儲存區域劃分

首先,我們先了解一下資料在記憶體中的儲存方式,根據變數值的生存週期,可以分為靜態儲存區和動態儲存區。如下:

所謂靜態儲存區是指在程式執行期間分配固定的儲存空間的方式,而動態儲存區是指程式執行期間根據需要進行動態分配儲存空間的方式。

靜態變數和全域性變數儲存在靜態儲存區,在程式開始執行時給全域性變數分配儲存區,程式執行完畢後釋放。在程式執行過程中它們佔據固定的儲存單元,而不是動態地進行分配和釋放。

動態儲存區主要儲存一下資料:

1、函式形式引數。在呼叫函式時給形參分配儲存空間。

2、自動變數。

3、函式呼叫時的現場保護和返回地址。

這裡,我們習慣把動態儲存區分為堆區和棧區。棧區由系統自動管理釋放,堆區由GC進行管理釋放。

瞭解了資料的儲存方式,我們繼續瞭解C#中的資料型別。

C#中的所有資料型別都可以分為兩類:值型別和引用型別。它們的區別來源於它們的複製方式:值型別的資料總是被值複製;而引用型別的資料總是被引用複製。

值型別包含值,換言之,變數引用的位置就是值在記憶體中實際儲存的位置。因此,將第一個變數的值賦給第二個變數會在新變數的位置建立原始變數的值的一個記憶體副本。相同值型別的第二個變數不能引用和第一個變數相同的記憶體位置。所以,更改第一個變數的值不會影響第二個變數的值。

引用型別和引用它們的變數指向資料儲存位置。引用型別並不直接儲存值,它們儲存的是對一個記憶體位置的引用(記憶體地址)。換言之,當我們建立一個引用型別的變數時,是建立了一個指向堆記憶體塊的引用。如下:

這裡需要注意的是,引用型別在複製的時候,複製的是地址的記憶體副本。無論引用型別所引用的記憶體地址塊有多大,實際上傳遞的只是儲存在記憶體棧上的地址,所以,引用型別的複製效率相比值型別更高。

特殊說明:

1、string型別為引用型別,等號操作相當於new操作。

2、陣列是引用型別,無論陣列成員是什麼型別。

3、C#中所有引用型別的複製都是一種淺複製操作,想要實現深度複製,型別需要實現IClone介面。

4、為引用型別變數申請的儲存區由CLR中的垃圾回收機制進行回收,但並不是所有的型別都會自動回收。如:非託管變數。