[TOC] C 學習筆記之值類型與引用類型 1.值類型與引用類型 1.1 深層區別 值類型與引用類型有不同的記憶體分佈,這導致了不同的記憶體管理機制: 值類型由OS負責記憶體管理 引用類型由垃圾回收器(GC)負責記憶體管理 記憶體管理:指的是對記憶體的分配與釋放的管理 1.2 值類型與引用類型的嵌套使用 1.2 ...
[TOC]
C#學習筆記之值類型與引用類型
1.值類型與引用類型
1.1 深層區別
值類型與引用類型有不同的記憶體分佈,這導致了不同的記憶體管理機制:
- 值類型由OS負責記憶體管理
- 引用類型由垃圾回收器(GC)負責記憶體管理
記憶體管理:指的是對記憶體的分配與釋放的管理
1.2 值類型與引用類型的嵌套使用
1.2.1 引用類型嵌套值類型
eg 1.類的欄位值是值類型,它是在托管堆上的。
eg 2.局部變數(如方法中的變數),是在堆棧上的。
1.2.2 值類型嵌套引用類型
堆棧保存了引用,托管堆保存了實際的數據。
1.3 小結
- 由於值類型由OS直接對記憶體進行管理,而引用類型需要使用托管堆對記憶體進行管理,所以值類型在性能上有天然的優勢;
- 引用類型可以具有繼承性(類,介面);
- 使用引用類型進行傳參時會改變變數本身(string除外,因為string具有不變形,賦值後不可改變。可以理解為const修飾符修飾的變數?);
- 值類型實例總會被分配到它聲明的地方,引用類型總被分配到托管堆上。
2.裝箱與拆箱
2.1 類型轉換的幾種方法
- 隱式的類型轉換(裝箱);
- 顯示轉換
- is和as運算符進行安全的類型轉換
- .NET類庫中的Conver進行類型轉換
2.2 什麼是裝箱與拆箱
graph TD; 值類型-->1裝箱;1裝箱-->引用類型;引用類型-->2拆箱;2拆箱-->值類型;值類型裝箱成為引用類型,引用類型拆箱成為值類型。
裝箱過程:在托管堆生成一份堆棧中值類型對象的備份。
- 記憶體分配:在托管堆中分配放置賦值的實際數據的空間;
- 完成實際數據的分配:將值類型實例的數據複製到新分配的空間中;
- 地址返回:將托管堆中的對象地址返回給引用類型變數。
拆箱過程:將托管堆中生成的引用類型所指向的已裝箱的值類型數據複製到值類型對象的過程。
- 檢查實例:是否為null,否則繼續檢查變數是否和拆箱後的類型是否為同一類型,是繼續;
- 地址返回:返回已經裝箱變數的實際數據部分地址;
- 數據複製:將托管堆中的數據複製到堆棧中。
2.3 一個裝箱與拆箱的例子
int i = 3;
object o = i; // 裝箱
int y = (int)o; // 拆箱
2.4 裝箱與拆箱帶來的問題
- 性能問題
- 中間帶有複製操作,會降低性能
- 產生中間對象,造成了GC(垃圾回收器)的負擔
- 會產生隱藏的bug
2.5 小結
- 值類型裝箱成為引用類型,引用類型拆箱成為裝箱前的值類型
- 裝箱會在托管堆生成堆棧中值類型對象的備份,根據這個備份可以完成拆箱
- 過多使用裝箱與拆箱操作會帶來性能問題與產生一些難以排除的bug