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

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

C#堆棧原理(我有兩個例子測試你到底會不會)

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

C#堆棧原理(我有兩個例子測試你到底會不會)

背景

  • 上次寫了一篇文章關于try finnally的一些疑問(被我用windows live覆蓋了,草),后來經過大神們解釋,我明白了在我理解了try、finnally運行原理后,還欠缺的就是關于值類型引用類型在內存中的存儲問題。

  • 我仔細拜讀了一些大神們的文章,主要的參考點是一個系列文章《譯文---C#堆VS棧》,里面詳細解釋了堆棧的要點,基礎差的禽獸們就別看我這個總結了。

    什么是堆棧

  • 堆棧在內存中可以理解為兩個不同的容器。

  • QQ20150520002345_thumb11棧:棧就是一個先入后出的存儲空間,必須按照順序依次執行。比QQ20150520002809_thumb5如一筒羽毛球,只有一個出入口,如果想取出來球,只能先把最后塞入的那個球拿出來才能繼續拿其他的球。

  • 堆:堆也是一個按序排列的存儲空間,不同的是,堆里面的數據可以隨便取。比如圖書館里的書都是按照一定順序排列的,但是取書的時候,可以直接拿出來自己需要的書籍而不用管其他的書籍。

  • 數據在堆棧中的存儲位置

  • 在堆棧上保存的數據分為四種:值類型、引用類型、指針、指令。

  • 值類型重點關注struct,因為其容易被認為成引用類型,而且其存儲的數據有時候很大,傳值時最好用ref;

  • 引用類型關注string,因為其雖然是引用類型,但是表現上是值類型,即通過形參傳入的string數據的操作不會影響實參。

  • 指針通常不會由我們顯示的使用,它們由公共語言運行時(CLR)來管理。指針(或引用)是不同于引用類型的,是因為當我們說某個事物是一個引用類型時就意味著我們是通過指針來訪問它的。指針是一塊內存空間,而它指向另一個內存空間。就像棧和堆一樣,指針也同樣要占用內存空間,但它的值是一個內存地址或者為空。(我復制的,我也不太懂

  • 指令,在我參考的文檔里好像并沒有提到,我理解的是,當JIT編譯器把方法的IL語句變為機器語言后,會將其存入到一個動態分配的內存空間,然后將地址返回給CLR的一個內部數據結構表(此表記錄一個類里面的所有方法的地址),因為指令相當于值類型,具體存儲位置可以參考值類型。

  • 類型存在位置的定律

    1. 引用類型總是在堆上創建。

    2. 值類型和指針類型總是在它聲明的地方創建。

    引用類型總是在堆上創建,然后將地址返回,地址的保存位置類似與值類型。

    值類型的存儲位置和聲明它的類型有關。當Main()執行的時候,會分配一個棧區,如果在Main()里面聲明了值類型,那么它就會保存在這個棧上;如果Main()先聲明了一個struct,而struct里面聲明了值類型,那么這個值類型也一樣保存在棧上,因為聲明這個值類型的類型即struct也在棧上;而如果聲明值類型的類型是一個引用類型,比如一個類,那么這個值類型就會保存在堆上。

    賦值時的區別

    值類型賦值就是一種深拷貝,即將值的內容傳遞過去,且不會受相互操作的影響。

    引用類型賦值是一種淺拷貝,只是將引用類型的地址傳遞了過去,比如A = B,那么A、B的操作都會相互影響。當然,string是一種特例,賦值或者傳參后不會相互影響。如果你想引用類型也能執行深拷貝,就要自己寫Clone()方法了。

    空間分配及回收

  • 堆和棧這里的區別具體不解釋,可以查看相關文檔,這里引用一位前輩的比喻來看出: 使用棧就象我們去飯館里吃飯,只管點菜(發出申請)、付錢、和吃(使用),吃飽了就走,不必理會切菜、洗菜等準備工作和洗碗、刷鍋等掃尾工作,他的好處是快捷,但是自由度小。

    使用堆就象是自己動手做喜歡吃的菜肴,比較麻煩,但是比較符合自己的口味,而且自由度大。比喻很形象,說的很通俗易懂,不知道你是否有點收獲。

    舉例

  • 以下是我想的兩個例子,如果你都能答對且明白原理,則說明你至少理解了堆棧。

    1、引用類型賦值,修改某一個引用類型,會有什么結果

           static void Main(string[] args)        {            var my = new MyInt();            var you = my;            you.index = 1;            you = null;            Console.WriteLine(my.index.ToString());            Console.ReadLine();        }        public class MyInt        {            public int index;        }
  • 結果是:1;而且沒有返回異常。(重點是為什么沒發生異常)?

    2、引用類型傳遞和指針傳遞(ref代表傳遞的是指針)的區別

          static void Main(string[] args)        {            PRogram main = new Program();            var my = new MyInt();            main.CommonMethod(my);            Console.WriteLine(my.index.ToString());            main.RefMethod(ref my);            Console.WriteLine(my.index.ToString());                   Console.ReadLine();        }        public void CommonMethod(MyInt myInt)        {            myInt.index = 1;            myInt = null;        }        public void RefMethod(ref MyInt myInt)        {            myInt.index = 2;            myInt = null;        }        public class MyInt        {            public int index;        }


  • 結果是1,然后異常;(為什么引用類型傳遞不異常,而指針傳遞異常)?


    疑問

  • 數據結構的棧和內存中的棧有什么區別嗎?網上說數據結構的棧是一個理論,一個是實現方式,那么數據結構中的隊列,在內存中有什么實現呢?還是說網上的說法是錯誤的?

  • 希望大神們幫我解釋一下。


  • 發表評論 共有條評論
    用戶名: 密碼:
    驗證碼: 匿名發表
    主站蜘蛛池模板: 万山特区| 平和县| 锡林浩特市| 福州市| 灵台县| 马尔康县| 香港 | 陕西省| 汉川市| 房山区| 黄浦区| 邹平县| 正宁县| 万山特区| 呈贡县| 旺苍县| 封开县| 义乌市| 遵义市| 洞口县| 石渠县| 商南县| 二连浩特市| 噶尔县| 高淳县| 林口县| 儋州市| 万载县| 德阳市| 达日县| 隆子县| 彭山县| 永嘉县| 外汇| 甘谷县| 岳西县| 株洲县| 呼伦贝尔市| 灵山县| 醴陵市| 获嘉县|