初學者常困惑:Cs cs1; 只是聲明引用,為何書上說「存儲在棧上」?本文用記憶體圖解徹底釐清引用變量與對象實例的空間分配關係。
new Cs() 時才在託管堆分配對象,並將地址寫入 `cs1`。| 階段 | 棧 | 堆 |
|---|---|---|
Cs cs1; | cs1 → 0x00000000 (null) | 無分配 |
cs1 = new Cs(); | cs1 → 0x02A4B8C0 | 0x02A4B8C0: [SyncBlockIndex][TypeHandle][欄位...] |
因為變量槽位在棧上。引用類型的「值」是地址,地址本身是值類型,按值類型規則存儲。區分 變量存儲位置(棧/堆/靜態區)與 對象實例存儲位置(永遠在堆),是理解 C# 記憶體模型的關鍵。
unsafe {
Cs cs1 = null;
Console.WriteLine($"cs1 address on stack: {(long)&cs1:X}");
cs1 = new Cs();
Console.WriteLine($"cs1 value (heap addr): {(long)Unsafe.AsPointer(ref cs1):X}");
}
輸出會顯示兩個不同地址:前者是棧上槽位,後者是堆上對象。