【转】深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第四节 参数传递对堆栈的影响 1
前言
?
雖然在.Net Framework 中我們不必考慮內在管理和垃圾回收(GC),但是為了優化應用程序性能我們始終需要了解內存管理和垃圾回收(GC)。另外,了解內存管理可以幫助我們理解在每一個程序中定義的每一個變量是怎樣工作的。
?
簡介
?
這篇文章我們將介紹一些方法參數傳遞行為在堆與棧中的影響。前幾節我們介紹了堆與棧的基本工作原理,程序執行時值類型與引用類型在堆棧中的存儲。另外,我們已經介紹了一些關于指針的基本知識。這一節中參數傳遞對堆棧的影響很重要,下面會慢慢道來。
?
參數,大畫面
下面是當代碼運行時會產生的一個詳細過程。上幾節已經介紹過當一個方法被調用時會產生的基本情況,讓我們來看一下更加詳細的內容。
當我們調用一個方法時會發生以下情形:
代碼:
?public int AddFive(int pValue)
{
int result;
result = pValue + 5;
return result;
}
棧像下圖所示:
?
注意:ReturnValue方法不會存在棧上,圖中把ReturnValue作為此棧結構的開始只是為了解釋棧原理。
?
像前幾節介紹的,值類型和引用類型在棧里的存儲是不同的。棧為任何值類型創建副本,棧也為任何引用類型的指針創建副本。
?
值類型傳遞
下面是值類型傳遞在棧里的內幕。
?
首先,當我們傳遞一個值類型變量時,棧會為它分配一塊內存空間并把值類型變量的值存儲進去。看下面的代碼:
?class Class1
{
public void Go()
{
int x = 5;
AddFive(x);
Console.WriteLine(x.ToString());
}
public int AddFive(int pValue)
{
pValue += 5;
return pValue;
}
}
當代碼執行時,棧為x分配一塊內存空間并存儲值5
然后,AddFive()被放到棧上,同時棧分配內存空間給參數pValue并復制x的值給它。
當AddFive()執行完成,線程被傳遞回Go()。同時因為AddFive()執行完,它的參數pValue也實質上被移除。
所以結果是5是合理的。關鍵點是任何被傳遞的值類型參數僅是一個碳復制,因為我們希望保護原始變量的值。
有一點要記住的是,如果我們有一個非常龐大的值類型(如,龐大的struct類型)傳遞到棧里,當處理器循環復制它并循環占有棧空間時將會非常耗資源。棧沒有無限的空間去使用,就像用水杯不斷的接水早晚會溢出一樣。Struct類型可以變得非常龐大,我們要小心并清醒的使用它。
?
下面是一個比較大的struct結構類型:
?public struct MyStruct
{
long a, b, c, d, e, f, g, h, i, j, k, l, m;
}
讓我們看看執行下面代碼Go()方法時再到DoSomething()方法會發生的情況:
public void Go()
{
MyStruct x = new MyStruct();
DoSomething(x);
}
public void DoSomething(MyStruct pValue)
{
// 省略具體實現....
}
這可能會非常低效。想像一下如果我們傳遞MyStruct幾千次,它會怎么樣讓程序死掉。
?
那么,我們怎么才能回避這樣的問題呢?那就是僅傳遞原始值類型的引用。
public void Go()
? ? ? ? ? {
? ? ? ? ? ? ?MyStruct x = new MyStruct();
? ? ? ? ? ? ?DoSomething(ref?x);
? ? ? ? ? ? ??
? ? ? ? ? }
?
? ? ? ? ? ?public struct MyStruct
? ? ? ? ? ?{
? ? ? ? ? ? ? ?long a, b, c, d, e, f, g, h, i, j, k, l, m;
? ? ? ? ? ?}
?
? ? ? ? ? ?public void DoSomething(ref?MyStruct pValue)
? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? // 省略實現....
? ? ? ? ? ?}
?
?
這樣就能節省內存并提升內存使用效率
?
唯一需要注意的是傳遞引用時我們在訪問原始變量x的值,任可對pValue的改變都會影響到x。
下面的代碼會將x改變成"12345",因為pValue.a實際上指向原始x聲明時所在的內存地址。
?public void Go()
{
MyStruct x = new MyStruct();
x.a = 5;
DoSomething(ref x);
Console.WriteLine(x.a.ToString());
}
public void DoSomething(ref MyStruct pValue)
{
pValue.a = 12345;
}
未完待續。。。
?
?
翻譯:?http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory2B01142006125918PM/csharp_memory2B.aspx
?
總結
以上是生活随笔為你收集整理的【转】深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第四节 参数传递对堆栈的影响 1的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ETC信用卡
- 下一篇: 【转】C#Socket编程详解(一)TC