【转】深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第三节 栈与堆,值类型与引用类型
?
前言
?
雖然在.Net Framework 中我們不必考慮內(nèi)在管理和垃圾回收(GC),但是為了優(yōu)化應(yīng)用程序性能我們始終需要了解內(nèi)存管理和垃圾回收(GC)。另外,了解內(nèi)存管理可以幫助我們理解在每一個程序中定義的每一個變量是怎樣工作的。
?
?
簡介
?
本文將介紹值類型與引用類型在堆棧里的基本存儲原理。
?
值類型會存儲在堆里?
?
是的,值類型有時候就是會存儲在堆里。上一節(jié)中介紹的?黃金規(guī)則2:值類型和指針永遠存儲在它們聲明時所在的堆或棧里。如果一個值類型不是在方法中定義的,而是在一個引用類型里,那么此值類型將會被放在這個引用類型里并存儲在堆上。
?
代碼圖例
?
我們定義一個引用類型:
public class MyInt
{
public int MyValue;
}
里面包含一個值類型MyValue。
執(zhí)行下面的方法:
public MyInt AddFive(int pValue)
{
MyInt result = new MyInt();
result.MyValue = pValue + 5;
return result;
}
就像上一節(jié)介紹的一樣,線程開始執(zhí)行此方法,參數(shù)pValue將會被放到當前線程棧上。
?
接下來不同于上一節(jié)所介紹的是MyInt是一個引用類型,它將被放到堆上并在棧上放一個指針指向它在堆里的存儲。
?
當AddFive()執(zhí)行完成后,如上一節(jié)所講棧開始清理。
現(xiàn)在是需要C#垃圾回收GC的時候了。當我們的程序所占內(nèi)存到達臨界值時(即將溢出),我們會需要更多的堆空間,GC就會開始運行。GC停止所有當前運行線程(整體停止),找到堆里所有主程序不會訪問到的對象并刪除它們。然后,GC會識別所有堆里剩下的對象并分配內(nèi)存空間給它們,同時調(diào)整堆和棧里指向它們的指針。你可以想像這是非常耗資源的,這會影響到程序的性能。這就是為什么我們需要理解和注意堆棧的使用,進而寫出高性能代碼。
?
堆棧原理對代碼的影響
?
當我們使用引用類型時,我們在和指向引用類型的指針打交道,而不是引用類型本身。
當我們使用值類型時,我們就是在和值類型本身打交道。
?
代碼圖例
?
假設(shè)執(zhí)行方法:
public int ReturnValue()
{
int x = new int();
x = 3;
int y = new int();
y = x;
y = 4;
return x;
}
我們會得到值?3。
?
?
使用引用類型:
public class MyInt
{
public int MyValue;
}
?
如果執(zhí)行方法:
public int ReturnValue2()
{
MyInt x = new MyInt();
x.MyValue = 3;
MyInt y = new MyInt();
y = x;
y.MyValue = 4;
return x.MyValue;
}
我們得到的值是4而不是3!(譯外話:這是很簡單,但相信還是有很多人不知道原理的)
?
第一個示例中:
public int ReturnValue()
{
int x = 3;
int y = x;
y = 4;
return x;
}
?
x就是3,y就是4。操作兩個不同對象。
?
第二個示例:
public int ReturnValue2()
{
MyInt x;
x.MyValue = 3;
MyInt y;
y = x;
y.MyValue = 4;
return x.MyValue;
}
?
得到的值是4不是3是因為我們操作棧里兩個指針并且它們指向堆里同一個對象。
?
?
總結(jié)
?
希望這篇文章能幫助你更好的理解值類型變量與引用類型變量的不同,同時理解什么是指針,什么時候用到指針。以后的文章里會更深入的介紹C#內(nèi)存管理并詳細闡述方法參數(shù)。
?
翻譯于:?http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory01122006130034PM/csharp_memory.aspx
?
?
?
總結(jié)
以上是生活随笔為你收集整理的【转】深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第三节 栈与堆,值类型与引用类型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转】超详细的UML状态图符号,初学者也
- 下一篇: 电子专票没有加盖发票章可以吗