值類型與引用類型
值類型:數(shù)值類型,結(jié)構(gòu)體,枚舉,它是每一個實例都保存有各自的數(shù)據(jù)。值類型的變量直接存儲數(shù)據(jù),分配在托管棧中。變量會在創(chuàng)建它們的方法返回時自動釋放。
引用類型:數(shù)組,用戶定義的類、接口、委托,Object,字符串,NULL類,它是多實例共享一份數(shù)據(jù)。
值類型與引用類型的區(qū)別
最基本的區(qū)別是 "值類型"通過拷貝(在賦值,初始化,參數(shù)傳遞中)會創(chuàng)建一個擁有獨立數(shù)據(jù)的實例;引用類型拷貝, 從另一方面來說, 是隱式的創(chuàng)建了一個共享實例. 在拷貝后, 兩個變量實際引用到了同一個實例, 也就是說修改第二個變量的值同樣會影響原始值。
| 序號 | 值類型 | 引用類型 |
|---|---|---|
| 存儲方式 | 直接存儲數(shù)據(jù)本身 | 存儲的是數(shù)據(jù)的引用,數(shù)據(jù)存儲在數(shù)據(jù)堆中 |
| 內(nèi)存分配 | 分配在棧中 | 分配在堆中 |
| 效率 | 效率高,不需要地址轉(zhuǎn)換 | 效率低,需要進(jìn)行地址轉(zhuǎn)換 |
| 內(nèi)存回收 | 使用完后立即回收 | 使用完后不立即回收,而是交給GC處理回收 |
| 賦值操作 | 創(chuàng)建一個新對象 | 創(chuàng)建一個引用 |
| 類型擴展 | 不易擴展,所有值類型都是密封(seal)的,所以無法派生出新的值類型 | 具有多態(tài)的特性方便擴展 |
| 實例分配 | 通常是在線程棧上分配的(靜態(tài)分配),但是在某些情形下可以存儲在堆中 | 總是在進(jìn)程堆中分配(動態(tài)分配) |
引用類型和值類型在內(nèi)存中怎么存儲?
值類型-在棧內(nèi)存中存儲
引用類型-在托管堆內(nèi)存中存儲
棧與堆的不同!
引用類型實例存在堆中,值類型實例比如結(jié)構(gòu)存在于一個稱為棧的內(nèi)存區(qū)域中。如果值類型實例是一個類的一部分,值會和類一起存在堆中。
棧被用于靜態(tài)存儲分配,堆被用于動態(tài)存儲分配,它們都存在計算機的RAM中。
棧被CPU緊密管理并優(yōu)化,當(dāng)一個函數(shù)創(chuàng)建一個變量,棧會存儲這個變量,并在函數(shù)退出時候被毀掉。被分配到棧的變量直接存儲在內(nèi)存上,訪問這段內(nèi)存非常快。當(dāng)一個函數(shù)或者方法調(diào)用另一個函數(shù),另一個函數(shù)再依次調(diào)用其他函數(shù)等等,直到最后一個函數(shù)返回它的值之前,其他所有函數(shù)都會保持暫停執(zhí)行。
棧總是按照LIFO順序保留,最新保留的區(qū)塊總是會下一個釋放。這使得跟蹤記錄棧非常簡單,釋放一個棧上的區(qū)塊不過是調(diào)整一個指針。因為棧非常組織有序,所以它快捷高效。
系統(tǒng)使用堆存儲被其他對象引用的數(shù)據(jù),堆是一大片內(nèi)存,系統(tǒng)可以從中請求并動態(tài)分配內(nèi)存區(qū)塊。堆并不會像棧一樣自動毀掉它的對象,需要外部工作來處理這些。在蘋果設(shè)備中ARC就做這個工作。引用數(shù)量會被ARC追蹤,當(dāng)它變?yōu)?時對象會被釋放。因此整個過程(分配,追蹤引用,釋放)會比棧要慢。所以值類型要快于引用類型。