<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      小記一次讓我誤會的引用傳參

      大部分時候,引用類型和值類型的區別是顯而易見的,但在用引用類型作為方法參數時,卻多次引起了我的誤解,每次都得對著電腦抓狂一下才又一次發現問題所在。

      問題在于如下代碼段:
      Code Segment 1

      此時會輸出20,這很明顯,現在加上了一個方法AddAgeB:
      public static void AddAgeB(Person p)


      當把Main方法中的AddAgeA(p)改成AddAgeB(p)后,就輸出了10,而不再是20。

      于是我自言自語:不是說class都是引用類型么?AddAgeB一樣是接收一個引用類型Person,雖然方法體中新new了一個Person,但是緊跟在后面的一句一樣對這個引用類型的age字段賦值了啊?
      在Main方法中Person p = new Person() (#1處)時,在堆中就分配了一塊空間,下一句向這塊空間中的age所在的內存空間存入了10,然后把p這個引用傳遞給AddAgeB()方法,在AddAgeB()中又在堆中開辟了一塊新的空間(#2處),然后把新開辟的內存地址賦給p,下一句把新空間中的age賦為20,這么說來,Main()中的輸出應該變成20了啊?難道這樣不對么?

      我抓狂了一下后發現,上面我的自言自語中缺失了一個很重要的細節,而這個細節,就是關鍵所在。問題出在這一句:“然后把p這個引用傳遞給AddAgeB()方法”,這太含糊了,我忘記了這里的“引用傳遞”其實是一個“復制”的過程。在上面兩個AddAge方法體中的p,其實只是Main方法中的p的一個副本,當執行:Person p = new Person() 時,會在托管堆上開辟一塊地址空間,存放Person的一個實例,這個實例的age字段就存在這個空間里頭,同時,在棧上還會分配一塊內存空間,它用來存放Person實例所在的堆內存地址,而p的值,就是棧上的這個地址。當執行 AddAgeA(p) 或 AddAgeB(p)時,棧上p的值(內存地址)會被復制,而在AddAge方法體中所使用的p,就是這個復制出來的副本,而不是原來的p,但是,它們的值(地址)是一樣的,都是指向托管堆中的Person實例地址,所以,在AddAgeA()中,當執行p.age = 20時,托管堆中的那個Person實例的age字段的值就變成了20,于是,在Main方法中輸出時,因為Main方法中的p也是指向這塊堆空間地址,所以輸出了20。

      而在AddAgeB()中,有關鍵的一句:p = new Person(),這一句會在托管堆中再開辟一塊新的內存空間,把后把它的地址賦給棧上的p,在這個時候,Main方法中的p和AddAgeB方法中的p不僅在棧上的位置不一樣,值也不一樣,當在執行下一句:p.age = 20;時,新開辟的堆空間中的age的值的的確確是改變了,但是在出了方法體的右花括號之后,方法體中的p(在棧上)就因為作用域的原因而被釋放,那么,AddAgeB方法中創建的那個Person實例就成了一個等待GC來回收的垃圾,因為此時堆中存在了兩個Person實例,在Main方法中的那個p所指向的堆空間中的age并沒有被改變,所以在Main方法中輸出了10。

      再回頭看看裝箱:

      Box Main

      很顯然,此時輸出了 a = 5 , obj = 10。
      在第二行中,有一個裝箱操作,a的值為被“復制”一份到obj中,所以a的值不變,obj的值在執行obj = 10之后變了。

      現在改一下:
      public static void Main() {
          
      int a = 5;
          
      object obj = a;
          Change(obj);
          Console.WriteLine(
      "a = " + a);
          Console.WriteLine(
      "obj = " + obj);
      }

      public void Change(object obj) {
          obj 
      = 10;
      }

      此時會輸出什么呢?
      正確答案是a = 5, obj = 5

      由此也可得知,當在Change方法體中執行obj = 10時,10會被裝到托管堆中的箱子里面去,然后obj的值被重新賦為這個箱子所在的起始地址,由于方法體中的obj引用的值跟Main方法中的obj引用的值并不一樣,所以,輸出的obj還是5。

      總結一下,其實就是幾個字:

      如果沒有用ref或out關鍵字的話,在給方法傳遞參數時,會有一個復制的過程,不管是值類型還是引用類型。


      當然,用上了ref的話,就沒有了這個復制過程,Main方法中的p和AddAge方法中的p就是實實在在的同一個引用了。
      posted @ 2008-06-18 23:23  水言木  閱讀(324)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 69天堂人成无码免费视频| 熟女一区| 老子午夜精品888无码不卡| 少妇人妻综合久久中文字幕| 国产超高清麻豆精品传媒麻豆精品 | 国产区成人精品视频| 国产欧美日韩亚洲一区二区三区| 蜜臀精品视频一区二区三区| av在线播放国产一区| 天堂网在线.www天堂在线资源| 精品国产中文字幕av| 国产一区一一区高清不卡| 国产精品一区二区中文| 三男一女吃奶添下面视频| 国产精品一区二区三区黄色| 亚洲香蕉网久久综合影视| 德庆县| 韩国午夜理伦三级| 99精品久久精品| 黑人巨大粗物挺进了少妇| 平乡县| 起碰免费公开97在线视频 | 精品亚洲国产成人av在线| 中文字幕无码专区一VA亚洲V专| 国产毛片基地| 国产精品高潮无码毛片| 日韩av中文字幕有码| 国产精品久久国产丁香花| 中文熟妇人妻av在线| 中文字幕无码不卡在线| 色综合久久天天综线观看| 免费无码毛片一区二三区| 国产成人永久免费av在线| 99中文字幕精品国产| 午夜成人鲁丝片午夜精品| 亚洲国产综合一区二区精品| 小嫩批日出水无码视频免费| 天等县| 成人福利国产午夜AV免费不卡在线 | 久久国内精品自在自线91| 精品人妻伦九区久久aaa片|