聲明一個值類型變量,編譯器會在棧上分配一個空間,這個空間對應着該值類型變量,空間裏存儲的就是該變量的值。指針
引用類型的實力分配在堆上,新建一個引用類型實例,獲得的變量對應的是該實例的內存分配地址,這就像您的銀行帳號同樣。code
1: public static class BoxingAndUnboxing 2: { 3: public static void Demonstration() 4: { 5: int ageInt = new int(); 6: 7: // Boxing operation. 8: object ageObject = ageInt; 9: 10: //ageObject = null; 11: 12: // Unboxing operation. 13: ageInt = (int)ageObject; 14: 15: Console.WriteLine(ageInt); 16: } 17: }
在該方法中,咱們首先聲明瞭一個值類型變量ageint,但並未給它賦值,接着聲明瞭一個典型的引用類型變量ageobject,並把ageint賦給它,這裏就進行了一次裝箱操做。編譯器如今託管堆上分配一塊內存空間(空間大小爲對象中包含的值類型變量所佔空間總和外加一個方法表指針和一個syncblockindex),而後把ageint拷貝到這個空間中,再返回該空間的引用地址,接下來第13行是拆箱操做,編譯器獲取到ageobject對象中值類型變量的指針,而後將其值拷貝給值類型變量。若是你把第10行的代碼打開,程序不會報錯,最後打印出個0,這說明在聲明值類型變量時,若是沒有初始化賦值,編譯器會自動將其賦值爲0,既然值類型沒有引用,那麼它就不可能爲空。引用類型不同,它能夠爲空引用,一張過時做廢的銀行卡能夠存在。而若是將一個空的對象裝箱,編譯器上哪兒區找它裏面的值類型變量的指針呢?因此這也是拆箱操做須要注意的地方。對象
未裝箱的值類型分配在棧上而不是堆上,而棧又不是GC的地盤兒,所以GC根本不過問值類型變量的死活,一旦值類型變量的做用範圍一過,它所佔的空間就當即被回收掉,不勞GC親自動手。內存