久久r热视频,国产午夜精品一区二区三区视频,亚洲精品自拍偷拍,欧美日韩精品二区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

ASP.NET堆和棧二之值類(lèi)型和引用類(lèi)型的參數(shù)傳遞和內(nèi)存分配

瀏覽:62日期:2022-06-08 14:53:16

".NET的堆和棧"系列:

在" ASP.NET堆和棧一之基本概念和值類(lèi)型內(nèi)存分配"中,了解了"堆"和"棧"的基本概念,以及值類(lèi)型的內(nèi)存分配。我們知道:當(dāng)執(zhí)行一個(gè)方法的時(shí)候,值類(lèi)型實(shí)例會(huì)在"棧"上分配內(nèi)存,而引用類(lèi)型實(shí)例會(huì)在"堆"上分配內(nèi)存,當(dāng)方法執(zhí)行完畢,"棧"上的實(shí)例由操作系統(tǒng)自動(dòng)釋放,"堆"上的實(shí)例由.NET Framework的GC進(jìn)行回收。而本篇的重點(diǎn)要放在:值類(lèi)型和引用類(lèi)型參數(shù)的傳遞,以及內(nèi)存分配。

傳遞值類(lèi)型參數(shù)

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

大致過(guò)程如下:

1、值類(lèi)型變量x被放到"棧"上。

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

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

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

輸出結(jié)果:5

以上,在傳遞值類(lèi)型參數(shù)x的時(shí)候,實(shí)際上是把x一個(gè)字節(jié)一個(gè)字節(jié)地拷貝給pValue。

傳遞容易造成"棧溢出"的值類(lèi)型參數(shù),在值類(lèi)型參數(shù)前加關(guān)鍵字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....}

假設(shè)以上的值類(lèi)型struct足夠大,而x和pValue都會(huì)被分配到"棧"上,這時(shí)可能造成"棧溢出"。

如何避免呢?
--解決辦法是讓DoSomething傳遞一個(gè)ref類(lèi)型參數(shù)。這樣寫(xiě):

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后,執(zhí)行DoSomething(ref x),是把x的地址賦值給了pValue,即pValue和x指向了同一個(gè)引用地址。當(dāng)改變pValue的值,變化也會(huì)反映到x中。

輸出結(jié)果:12345

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

傳遞引用類(lèi)型參數(shù)

傳遞引用類(lèi)型參數(shù)的道理和在傳遞的值類(lèi)型參數(shù)前面加ref關(guān)鍵字是一樣的。

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;}

輸出結(jié)果:12345

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

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

傳遞引用類(lèi)型參數(shù),在引用類(lèi)型參數(shù)之前加關(guān)鍵字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();}

輸出結(jié)果:
x is Animal : False
x is Vegetable : True

以上大致過(guò)程是這樣:
1、在托管堆上創(chuàng)建Animal對(duì)象實(shí)例。
2、在棧上創(chuàng)建類(lèi)型為T(mén)hing的x變量指向Animal實(shí)例的引用地址。
3、通過(guò)Switcharoo(ref x)方法把x本身的地址賦值給pValue,至此,pValue和x指向了相同的棧內(nèi)存地址,任何一方的變化都會(huì)反映到另外一方。

4、在Switcharoo(ref Thing pValue)內(nèi)部,在托管堆上創(chuàng)建Vegetable對(duì)象實(shí)例。
5、pValue指向Vegetable實(shí)例,也就相當(dāng)于x指向Vegetable實(shí)例。

以上,當(dāng)在引用類(lèi)型參數(shù)之前加上關(guān)鍵字ref,再傳遞,是把x本身的棧地址拷貝給pValue,x和pValue指向同一個(gè)棧地址。

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接

標(biāo)簽: ASP.NET
相關(guān)文章:
主站蜘蛛池模板: 彰化县| 嘉荫县| 贵州省| 绍兴市| 开封县| 钟祥市| 合水县| 体育| 子洲县| 平乐县| 彭州市| 永嘉县| 武川县| 习水县| 鄂尔多斯市| 如东县| 阿拉尔市| 卢氏县| 大石桥市| 长宁县| 肇源县| 蒙自县| 岱山县| 凯里市| 剑河县| 保亭| 蓝山县| 甘孜县| 靖州| 长岭县| 南昌市| 尚志市| 旌德县| 辽阳县| 赤峰市| 丽江市| 高青县| 吴江市| 松桃| 湖北省| 东宁县|