[译].Net中的内存-什么分配在了哪里
原文鏈接:https://jonskeet.uk/csharp/memory.html
人們在理解值類型和引用類型之間的差異時因為“值類型在棧上分配,引用類型在堆上分配”這句話造成了很多混亂。這完全是不對的,本文試圖澄清這個問題。
變量中有什么?
理解.NET中內(nèi)存工作方式的關(guān)鍵是理解變量是什么,以及它的值是什么。在最基本的層面上,變量是變量名和內(nèi)存之間的關(guān)聯(lián)。變量的值是與之關(guān)聯(lián)的內(nèi)存中的內(nèi)容。該值占用內(nèi)存空間的大小和值的解釋取決于變量的類型 - 這正是值類型和引用類型之間的差異所在。
引用類型變量的值始終是引用或null。如果是引用,則它必須是與其變量類型兼容的對象的引用。例如,以Stream s聲明的變量s的值是null或Stream類型(或其兼容類型)實例的引用。引用類型變量所占內(nèi)存空間的大小是引用的大小,引用的大小在32位模式下固定為4個字節(jié),在64位模式下固定為8個字節(jié)。
值類型變量的值始終是其對象本身的值。例如,對于給定的結(jié)構(gòu):
? 以PairOfInts pair聲明的變量pair的值是整數(shù)對本身,而不是對一對整數(shù)的引用。其所占內(nèi)存空間則是兩個整數(shù)的大小,即8個字節(jié)。請注意,值類型變量永遠不能賦值為null - 因為這沒有任何意義,值類型變量不是一個引用。
那么東西存放在哪里?
變量的分配位置取決于聲明它的上下文:
局部變量在棧上分配。這包括引用類型變量 - 變量本身位于棧上,其引用的值分配在堆上。方法參數(shù)也計為局部變量,但如果使用ref、out、in修飾符修飾它們,則它們不再是原始類型,而是轉(zhuǎn)換為托管指針類型(Type &),此時傳遞的是原變量的指針,不再是變量本身。
引用類型的對象始終在堆上分配。
值類型的對象始終內(nèi)聯(lián)分配。即在方法中聲明的值類型變量在棧上分配,而作為類的實例字段的值類型變量將在堆上分配。
靜態(tài)變量在堆上分配,包括引用類型和值類型中聲明的靜態(tài)變量。無論創(chuàng)建多少個實例,靜態(tài)變量都共享一個內(nèi)存空間。
上述規(guī)則有幾個例外:在使用匿名方法時的外部變量和迭代器中的局部變量會由編譯器優(yōu)化為其它類型的實例字段,這些變量會轉(zhuǎn)移到堆中分配。
舉個例子
上述文字描述可能聽起來有點復雜,但一個完整的例子可以讓事情更清楚一些:
? 讓我們看一下標記“XXX”位置時內(nèi)存中的內(nèi)容。
在棧上分配一個PairOfInts類型的對象,對應變量z。
在堆上分配一個Test類型的對象,在棧上分配一個引用指向該對象,對應變量t1。以32位模式舉例,該對象在堆中占用20個字節(jié):8個字節(jié)的頭信息(所有堆對象都有),8個字節(jié)用于存儲PairOfInts實例,4個字節(jié)用于存儲字符串引用。
在堆上分配一個Test類型的對象,在棧上分配一個引用指向該對象,對應變量t2。該對象與上面的對象非常相似。
在棧上分配一個引用,對應變量t3。這個引用是null - 它沒有引用任何對象。
在棧上分配一個引用,對應變量t4,并賦值t1引用的對象,此時t1和t4引用堆內(nèi)存中的同一個對象。
最后,在堆內(nèi)存中有一個靜態(tài)變量PairOfInts.counter。
原文:https://www.cnblogs.com/minotauros/p/11254159.html
.NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總?http://www.csharpkit.com?
總結(jié)
以上是生活随笔為你收集整理的[译].Net中的内存-什么分配在了哪里的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一句话概括4本管理著作
- 下一篇: 上车时机已到--.NETCore是适应时