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

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

聽起來很吊的堆與棧其實也不過如此

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

聽起來很吊的堆與棧其實也不過如此

一、在講堆棧之前,我們先看看值類型和引用類型:

1,我們看看值類型與引用類型的存儲方式:

引用類型:引用類型存儲在堆中。類型實例化的時候,會在堆中開辟一部分空間存儲類的實例。類對象的引用還是存儲在棧中。

值類型:值類型總是分配在它聲明的地方,做為局部變量時,存儲在棧上;類對象的字段時,則跟隨此類存儲在堆中。

什么是堆什么是棧我們后面解釋。

圖1-1

2,我們再看看引用類型與值類型的區別:

①引用類型和值類型都繼承自Systerm.Object類。不同之處,幾乎所有的引用類型都是直接從Systerm.Object繼承,而值類型則是繼承Systerm.Object的子類Systerm.ValueType類。

②我們在給引用類型的變量賦值的時候,其實只是賦值了對象的引用;而給值類型變量賦值的時候是創建了一個副本(副本不明白?說通俗點,就是克隆了一個變量)。

文字不夠形象?我們上代碼看看

圖1-2

3,我們再看看引用類型和值類型的內存分配情況(我們對著代碼與圖看)

圖1-3

圖1-4

看了圖1-3和圖1-4之后,你們可能問我了:你是怎么知道變量在棧中的地址的。嘿嘿,等下教你用c#玩指針

從上面兩張圖我們可以看出:

①棧的結構是后進先出,也就是說:變量j的生命周期在變量s之前結束,變量s的生命周期在變量i之前結束,

②棧地址從高往底分配

③類型的引用也存儲在棧中

二、對于堆和棧的詳細介紹,我們往下看。

1,有人老是搞不明白堆和棧的叫法。我來解釋下:

堆:在c里面叫堆,在c#里面其實叫托管堆。為什么叫托管堆,我們往下看。

棧:就是堆棧,因為和堆一起叫著別扭,就簡稱棧了。

2,托管堆:

托管堆不同于堆,它是由CLR(公共語言運行庫(Common Language Runtime))管理,當堆中滿了之后,會自動清理堆中的垃圾。所以,做為.net開發,我們不需要關心內存釋放的問題。

3,有人老是搞不清楚內存堆棧與數據結構堆棧,我們來看看什么是內存堆棧,什么是數據結構堆棧

①數據結構堆棧:是一種后進先出的數據結構,它是一個概念,圖4-1中可以看出,棧是一種后進先出的數據結構。

②內存堆棧:存在內存中的兩個存儲區(堆區,棧區)。

      棧區:存放函數的參數、局部變量、返回數據等值,由編譯器自動釋放

      堆區:存放著引用類型的對象,由CLR釋放

三、最后我們用c#玩一玩指針

1,首先右鍵項目-->屬性-->生成-->勾選允許不安全代碼

2,在寫不安全代碼的時候需要加上unsafe

    //標記類    unsafe public class Student    {        //標記字段        unsafe int* pAge;        //標記方法        unsafe void getType(int* a)        {            //標記代碼段            unsafe            {                int* pAbc;      //聲明指針語法            }        }    }

  

3,指針的語法

            unsafe            {                int* pWidth, pHeight;                double* PResult;                byte*[] pByte;                //&:表示“取地址”,并把一個值數據類型轉換為指針,例如,int轉換為*int。這個運算稱為【尋址運算符】                //*:表示“獲取地址內容”,把一個指針轉換為一個值數據類型(例如:*float轉換為float)。這個運算符被                    //稱為“間接尋址運算符”(有時稱“取消引用運算符”)                int a = 10;//聲明一個值類型,給它賦值10                int* pA, pB;//聲明2個指針                pA = &a;//取出值類型a的地址,賦值給指針pA                pB = pA;//把指針pA的地址賦值給pB                *pB = 20;//獲取pB指向的地址內容,并賦值20                Console.WriteLine(a);//輸出20            }

  

4,將指針強制轉化為整數類型(只能轉化為uing、long、ulong類型)

int a = 10;int* pA, pB;pA = &a;uint address = (uint)pA;//將指針地址強制轉換為整數類型pB = (int*)address;//將整數類型強制轉換為指針*pB = 20;//指針指向aConsole.WriteLine(a);//輸出20

  

5,指針類型的強制裝換

int b = 10;int* pIa;double* pDa;pIa = &b;pDa = (double*)pIa;//將int*強制轉換成double*

  

6,void指針(不指向任何數據類型的指針)

int c = 10;int* pAA;pAA = &c;void* pVa = (void*)pAA;//轉換viod指針

  

7,指針算數的運算(不允許對void指針進行運算)

int d = 10;int* pId;//如果地址為100000pId = &d;pId++;//結果:100004(int類型的大小為4個字節)

  

8,結構指針:指針成員訪問運算符

①指針不能只想任何引用類型②結構里面不能包含引用類型

MyStruct* pStruct;MyStruct ms = new MyStruct();pStruct = &ms;//--取地址內容賦值為10(*pStruct).X = 10;pStruct->X = 10;//--取地址賦值給pIsint* pIs1 = &(ms.X);int* pIs2 = &(pStruct->X); //結構struct MyStruct{        public int X = 1;        public int Y = 2;}

  

9,類成員指針

Person p = new Person();fixed (int* pip1 = &(p.X), pIp2 = &(p.Y)){}//pIp1和pIp2的生命周期//類class Person{     public int X;     public int Y;}

  

10,有趣的實驗

unsafe{//有趣的問題:為什么b的值改變了//回答:因為i的地址指向了bint a = 10;int b = 20;int* i;i = &a;//將a的地址賦值給指針ii -= 1;//將i的地址-1(相當于向下移動4個字節(int類型的大小為4個字節))*i = 30;//取出i指針指向的內容賦值為30Console.WriteLine(b);//輸出30}

  


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 蓬溪县| 张家界市| 澄城县| 潮安县| 和顺县| 鄂托克前旗| 三门峡市| 平阴县| 永春县| 邵阳县| 陵水| 米易县| 崇礼县| 咸宁市| 昌图县| 周宁县| 海阳市| 自贡市| 滨州市| 河西区| 桂平市| 河间市| 蒙自县| 佛学| 军事| 定安县| 海晏县| 富裕县| 东山县| 贞丰县| 彰武县| 太保市| 兰溪市| 富源县| 平阳县| 济宁市| 南江县| 阳西县| 丁青县| 镇远县| 星座|