值型別與引用型別(上

2021-09-23 21:25:19 字數 2596 閱讀 3894

本文將介紹以下內容:

1. 引言

買了新本本,忙了好幾天系統,終於開始了對值型別和引用型別做個全面的講述了,本系列開篇之時就是因為想寫這個主題,才有了寫個系列的想法。所以對值型別和引用型別的分析,是我最想成文的一篇,其原因是過去的學習過程中我就是從這個主題開始,喜歡以il語言來分析執行,也喜好從底層的過程來深入了解。這對我來說,似乎是一件找到了有效提高的方法,所以想寫的衝動就沒有停過,旨在以有效的方式來分享所得。同時,我也認為,對值型別和引用型別的把握,是理解語言基礎環節的關鍵主題,有必要花力氣來了解和深入。  

2. 一切從記憶體開始

2.1 基本概念

從上回《第七回:品味型別---從通用型別系統開始

》我們知道,clr支援兩種基本型別:值型別引用型別。因此,還是把msdn這張經典檢視拿出來做個鋪墊。

引用型別(reference type),引用型別例項分配在託管堆(managed heap)上,變數儲存了例項資料的記憶體引用。其在msdn中的定義為引用型別儲存對值的記憶體位址的引用,位於堆上。我們由上圖可知,引用型別可以是自描述型別、指標型別或介面型別。而自描述型別進一步細分成陣列和類型別。類型別是則可以是使用者定義的類、裝箱的值型別和委託。通常宣告為以下型別:class、inte***ce、delegate、object、string以及其他的自定義引用型別時,該變數即為引用型別。

下面簡單的列出我們型別的進一步細分,資料來自msdn,為的是給我們的概念中有清晰的型別概念,這是最基礎也是最必須的內容。

2.2 記憶體深入

2.2.1. 記憶體機制

那麼.net的記憶體分配機制如何呢?

using system;

public

class test

} 在上述的過程中,我們分別定義了值型別變數mystruct和引用型別變數myclass,並使用new操作符完成記憶體分配和初始化操作,此處new的區別可以詳見《第五回:深入淺出關鍵字---把new說透

》  的論述,在此不做進一步描述。而我們在此強調的是mystruct和myclass兩個變數在記憶體分配方面的區別,還是以乙個簡明的圖來展示一下:

我們知道,每個變數或者程式都有其堆疊,不同的變數不能共有同乙個堆疊位址,因此mystruct和mystruct2在堆疊中一定占用了不同的堆疊位址,儘管經過了變數的傳遞,實際的記憶體還是分配在不同的位址上,如果我們再對mystruct2變數改變時,顯然不會影響到mystruct的資料。從圖中我們還可以顯而易見的看出,mystruct在堆疊中包含其實例資料,而myclass在堆疊中只是儲存了其實例資料的引用位址,實際的資料儲存在託管堆中。因此,就有可能不同的變數儲存了同一位址的資料引用,當資料從乙個引用型別變數傳遞到另乙個相同型別的引用型別變數時,傳遞的是其引用位址而不是實際的資料,因此乙個變數的改變會影響另乙個變數的值。從上面的分析就可以明白的知道這樣乙個簡單的道理:值型別和引用型別在記憶體中的分配區別是決定其應用不同的根本原因,由此我們就可以很容易的解釋為什麼引數傳遞時,按值傳遞不會改變形參值,而按址傳遞會改變行參的值,道理正在於此。 

對於記憶體分配的更詳細位置,可以描述如下:

》。2.2.2. 巢狀結構

巢狀結構就是在值型別中巢狀定義了引用型別,或者在引用型別變數中巢狀定義了值型別,相信園子中關於這一話題的論述和關注都不是很多。因此我們很有必要發揮一下,在此就順藤摸瓜,從上文對.net的記憶體機制著手來理解會水到渠成。

值型別如果巢狀在引用型別時,也就是值型別在內聯的結構中時,其記憶體分配是什麼樣子呢? 其實很簡單,例如類的私有字段如果為值型別,那它作為引用型別例項的一部分,也分配在託管堆上。例如: 

public

class nestedvalueinref  

} 其記憶體分配圖可以表示為:

引用型別巢狀在值型別時,記憶體的分配情況為:該引用型別將作為值型別的成員變數,堆疊上將儲存該成員的引用,而成員的實際資料還是儲存在託管堆中。例如:

public

struct nestedrefinvalue

} 其記憶體分配圖可以表示為:

2.2.3. 乙個簡單的討論

通過上面的分析,如果我們現在有如下的執行時:

atype mytype = new atype[10];

試問:如果atype是值型別,則分配了多少記憶體;而如果atype是引用型別時,又分配了多少記憶體?

值型別與引用型別(上

本文將介紹以下內容 1.引言 買了新本本,忙了好幾天系統,終於開始了對值型別和引用型別做個全面的講述了,本系列開篇之時就是因為想寫這個主題,才有了寫個系列的想法。所以對值型別和引用型別的分析,是我最想成文的一篇,其原因是過去的學習過程中我就是從這個主題開始,喜歡以il語言來分析執行,也喜好從底層的過...

C 值型別與引用型別 上

c 中,變數是值還是引用僅取決於其資料型別。c 的基本資料型別都以平台無關的方式來定義。c 的預定義型別並沒有內置於語言中,而是內置於.net framework中。net使用通用型別系統 cts 定義了可以在中間語言 il 中使用的預定義資料型別,所有面向.net的語言都最終被編譯為il,即編譯為...

C 值型別與引用型別 上

原帖 1.主要內容 型別的基本概念 值型別深入 引用型別深入 值型別與引用型別的比較及應用 2.基本概念 c 中,變數是值還是引用僅取決於其資料型別。c 的基本資料型別都以平台無關的方式來定義,c 的預定義型別並沒有內置於語言中,而是內置於.net framework中。net使用通用型別系統 ct...