国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

.NET的堆和棧02,值類型和引用類型參數傳遞以及內存分配

2019-11-17 03:02:32
字體:
來源:轉載
供稿:網友

.NET的堆和棧02,值類型和引用類型參數傳遞以及內存分配

在" .NET的堆和棧01,基本概念、值類型內存分配"中,了解了"堆"和"棧"的基本概念,以及值類型的內存分配。我們知道:當執行一個方法的時候,值類型實例會在"棧"上分配內存,而引用類型實例會在"堆"上分配內存,當方法執行完畢,"棧"上的實例由操作系統自動釋放,"堆"上的實例由.NET Framework的GC進行回收。而本篇的重點要放在:值類型和引用類型參數的傳遞,以及內存分配。

主要包括:■ 傳遞值類型參數■ 傳遞容易造成"棧溢出"的值類型參數,在值類型參數前加關鍵字ref■ 傳遞引用類型參數■ 傳遞引用類型參數,在引用類型參數之前加關鍵字ref

傳遞值類型參數

class Class1     {          public void Go()          {              int x = 5;              AddFive(x);               Console.WriteLine(x.ToString());                        }           public int AddFive(int pValue)          {              pValue += 5;              return pValue;          }     }

大致過程如下:

1、值類型變量x被放到"棧"上。8

2、開始執行AddFive()方法,值類型變量pValue被放到"棧"上,并把x的值賦值給pValue,pValue的值變成了5。9

3、繼續執行AddFive()方法,pValue的值變成了10。10

4、執行完AddFive()方法,釋放pValue的內存,"棧"指針回到x,線程重新回到Go()方法中。11

輸出結果:5

以上,在傳遞值類型參數x的時候,實際上是把x一個字節一個字節地拷貝給pValue。

傳遞容易造成"棧溢出"的值類型參數,在值類型參數前加關鍵字ref

public struct MyStruct           {               long a, b, c, d, e, f, g, h, i, j, k, l, m;           }          public void Go()          {             MyStruct x = new MyStruct();             DoSomething(x);                        }             public void DoSomething(MyStruct pValue)           {                    // DO SOMETHING HERE....           }

假設以上的值類型struct足夠大,而x和pValue都會被分配到"棧"上,這時可能造成"棧溢出"。

12

如何避免呢?--解決辦法是讓DoSomething傳遞一個ref類型參數。這樣寫:

public struct MyStruct           {               long a, b, c, d, e, f, g, h, i, j, k, l, m;           }          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;          }

使用ref后,執行DoSomething(ref x),是把x的地址賦值給了pValue,即pValue和x指向了同一個引用地址。當改變pValue的值,變化也會反映到x中。

13

輸出結果:12345

以上,為了避免"大型"值類型參數傳遞時造成的"棧溢出",可以在值類型前面加ref關鍵字,于是,在傳遞值類型參數x的時候,實際上是把x本身的棧地址拷貝給pValue,x和pValue指向同一個棧地址。

傳遞引用類型參數

傳遞引用類型參數的道理和在傳遞的值類型參數前面加ref關鍵字是一樣的。

public class MyInt           {               public int MyValue;           }          public void Go()          {             MyInt x = new MyInt();             x.MyValue = 2;              DoSomething(x);              Console.WriteLine(x.MyValue.ToString());                        }            public void DoSomething(MyInt pValue)           {               pValue.MyValue = 12345;           }

輸出結果:12345

以上大致過程是這樣:1、在托管堆上創建一個MyInt類型的實例2、在棧上創建一個MyInt類型的變量x指向堆上的實例3、把托管堆上的公共字段MyValue賦值為24、通過DoSomething(x)方法,把x的引用地址賦值給pValue,即pValue和x指向同一個引用地址5、改變pValue的值,也會反映到x上

以上,在傳遞引用類型參數x的時候,實際上是把x指向托管堆實例的引用地址拷貝給pValue,x和pValue指向同一個托管堆實例地址。

傳遞引用類型參數,在引用類型參數之前加關鍵字ref

public class Thing           {           }            public class Animal:Thing           {               public int Weight;           }            public class Vegetable:Thing           {               public int Length;           }          public void Go()          {             Thing x = new Animal();                        Switcharoo(ref x);               Console.WriteLine(                "x is Animal    :   "                + (x is Animal).ToString());               Console.WriteLine(                  "x is Vegetable :   "                  + (x is Vegetable).ToString());                        }            public void Switcharoo(ref Thing pValue)           {               pValue = new Vegetable();           }

輸出結果:x is Animal : Falsex is Vegetable : True

以上大致過程是這樣:1、在托管堆上創建Animal對象實例。2、在棧上創建類型為Thing的x變量指向Animal實例的引用地址。3、通過Switcharoo(ref x)方法把x本身的地址賦值給pValue,至此,pValue和x指向了相同的棧內存地址,任何一方的變化都會反映到另外一方。

14

4、在Switcharoo(ref Thing pValue)內部,在托管堆上創建Vegetable對象實例。5、pValue指向Vegetable實例,也就相當于x指向Vegetable實例。

15

以上,當在引用類型參數之前加上關鍵字ref,再傳遞,是把x本身的棧地址拷貝給pValue,x和pValue指向同一個棧地址。

參考資料:C# Heap(ing) Vs Stack(ing) in .NET: Part II《你必須知道的.NET(第2版)》,作者王濤。

".NET的堆和棧"系列包括:

.NET的堆和棧01,基本概念、值類型內存分配

.NET的堆和棧02,值類型和引用類型參數傳遞以及內存分配

.NET的堆和棧03,引用類型對象拷貝以及內存分配

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 英山县| 甘德县| 祁阳县| 绥宁县| 德州市| 林西县| 新和县| 德清县| 南开区| 宁武县| 肥城市| 天门市| 益阳市| 曲阜市| 黄梅县| 明溪县| 克东县| 南皮县| 定边县| 株洲市| 延川县| 内黄县| 壶关县| 鱼台县| 灵武市| 左云县| 娱乐| 车险| 宜丰县| 进贤县| 苏尼特右旗| 水城县| 扎囊县| 城步| 大宁县| 谷城县| 德清县| 金山区| 奉化市| 寿光市| 泸水县|