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

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

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

      [你必須知道的.NET] 第八回:品味類型---值類型與引用類型(上)-內存有理

      發布日期:2007.5.23 作者:Anytao

      ?2007 Anytao.com ,原創作品,轉貼請注明作者和出處。

       

      本文將介紹以下內容:

      • 類型的基本概念 
      • 值類型深入
      • 引用類型深入
      • 值類型與引用類型的比較及應用

       

      1. 引言

      買了新本本,忙了好幾天系統,終于開始了對值類型和引用類型做個全面的講述了,本系列開篇之時就是因為想寫這個主題,才有了寫個系列的想法。所以對值類型和引用類型的分析,是我最想成文的一篇,其原因是過去的學習過程中我就是從這個主題開始,喜歡以IL語言來分析執行,也喜好從底層的過程來深入了解。這對我來說,似乎是一件找到了有效提高的方法,所以想寫的沖動就沒有停過,旨在以有效的方式來分享所得。同時,我也認為,對值類型和引用類型的把握,是理解語言基礎環節的關鍵主題,有必要花力氣來了解和深入。  

      2. 一切從內存開始

      2.1 基本概念

      從上回《第七回:品味類型---從通用類型系統開始》我們知道,CLR支持兩種基本類型:值類型引用類型。因此,還是把MSDN這張經典視圖拿出來做個鋪墊。

       

      值類型(Value Type),值類型實例通常分配在線程的堆棧(stack)上,并且不包含任何指向實例數據的指針,因為變量本身就包含了其實例數據。其在MSDN的定義為值類型直接包含它們的數據,值類型的實例要么在堆棧上,要么內聯在結構中。我們由上圖可知,值類型主要包括簡單類型、結構體類型和枚舉類型等。通常聲明為以下類型:int、char、float、long、bool、double、struct、enum、short、byte、decimal、sbyte、uint、ulong、ushort等時,該變量即為值類型。  

      引用類型(Reference Type),引用類型實例分配在托管堆(managed heap)上,變量保存了實例數據的內存引用。其在MSDN中的定義為引用類型存儲對值的內存地址的引用,位于堆上。我們由上圖可知,引用類型可以是自描述類型、指針類型或接口類型。而自描述類型進一步細分成數組和類類型。類類型是則可以是用戶定義的類、裝箱的值類型和委托。通常聲明為以下類型:class、interface、delegate、object、string以及其他的自定義引用類型時,該變量即為引用類型。

      下面簡單的列出我們類型的進一步細分,數據來自MSDN,為的是給我們的概念中有清晰的類型概念,這是最基礎也是最必須的內容。

        

      2.2 內存深入

      2.2.1. 內存機制

      那么.NET的內存分配機制如何呢?

      數據在內存中的分配位置,取決于該變量的數據類型。由上可知,值類型通常分配在線程的堆棧上,而引用類型通常分配在托管堆上,由GC來控制其回收。例如,現在有MyStruct和MyClass分別代表一個結構體和一個類,如下:

      using System;

      public class Test
      {
          
      static void Main()
          {
              
      //定義值類型和引用類型,并完成初始化
              MyStruct myStruct = new MyStruct();
              MyClass myClass 
      = new MyClass();
              
              
      //定義另一個值類型和引用類型,
              
      //以便了解其內存區別
              MyStruct myStruct2 = new MyStruct();
              myStruct2 
      = myStruct;
              
              MyClass myClass2 
      = new MyClass();
              myClass2 
      = myClass;        
          }
      }

      在上述的過程中,我們分別定義了值類型變量myStruct和引用類型變量myClass,并使用new操作符完成內存分配和初始化操作,此處new的區別可以詳見《第五回:深入淺出關鍵字---把new說透》  的論述,在此不做進一步描述。而我們在此強調的是myStruct和myClass兩個變量在內存分配方面的區別,還是以一個簡明的圖來展示一下:

       

      我們知道,每個變量或者程序都有其堆棧,不同的變量不能共有同一個堆棧地址,因此myStruct和myStruct2在堆棧中一定占用了不同的堆棧地址,盡管經過了變量的傳遞,實際的內存還是分配在不同的地址上,如果我們再對myStruct2變量改變時,顯然不會影響到myStruct的數據。從圖中我們還可以顯而易見的看出,myStruct在堆棧中包含其實例數據,而myClass在堆棧中只是保存了其實例數據的引用地址,實際的數據保存在托管堆中。因此,就有可能不同的變量保存了同一地址的數據引用,當數據從一個引用類型變量傳遞到另一個相同類型的引用類型變量時,傳遞的是其引用地址而不是實際的數據,因此一個變量的改變會影響另一個變量的值。從上面的分析就可以明白的知道這樣一個簡單的道理:值類型和引用類型在內存中的分配區別是決定其應用不同的根本原因,由此我們就可以很容易的解釋為什么參數傳遞時,按值傳遞不會改變形參值,而按址傳遞會改變行參的值,道理正在于此。 

      對于內存分配的更詳細位置,可以描述如下:

      • 值類型變量做為局部變量時,該實例將被創建在堆棧上;而如果值類型變量作為類型的成員變量時,它將作為類型實例數據的一部分,同該類型的其他字段都保存在托管堆上,這點我們將在接下來的嵌套結構部分來詳細說明。
      • 引用類型變量數據保存在托管堆上,但是根據實例的大小有所區別,如下:如果實例的大小小于85000Byte時,則該實例將創建在GC堆上;而當實例大小大于等于85000byte時,則該實例創建在LOH(Large Object Heap)堆上。

      更詳細的分析,我推薦《類型實例的創建位置、托管對象在托管堆上的結構》。

      2.2.2. 嵌套結構 

      嵌套結構就是在值類型中嵌套定義了引用類型,或者在引用類型變量中嵌套定義了值類型,相信園子中關于這一話題的論述和關注都不是很多。因此我們很有必要發揮一下,在此就順藤摸瓜,從上文對.NET的內存機制著手來理解會水到渠成。

      • 引用類型嵌套值類型

      值類型如果嵌套在引用類型時,也就是值類型在內聯的結構中時,其內存分配是什么樣子呢? 其實很簡單,例如類的私有字段如果為值類型,那它作為引用類型實例的一部分,也分配在托管堆上。例如:

      public class NestedValueinRef

        
      //aInt做為引用類型的一部分將分配在托管堆上 
        private int aInt;  
        
      public NestedValueinRef 
        { 
          
      //aChar則分配在該段代碼的線程棧上 
           char achar = 'a'
        } 

      其內存分配圖可以表示為:

        

      •  值類型嵌套引用類型

      引用類型嵌套在值類型時,內存的分配情況為:該引用類型將作為值類型的成員變量,堆棧上將保存該成員的引用,而成員的實際數據還是保存在托管堆中。例如:

      public struct NestedRefinValue
      {
          
      public MyClass myClass;
          
      public NestedRefinValue
          {
              myClass.X 
      = 1;
              myClass.Y 
      = 2;
          }
      }

      其內存分配圖可以表示為:

       

      2.2.3. 一個簡單的討論

      通過上面的分析,如果我們現在有如下的執行時:

      AType[] myType = new AType[10];

      試問:如果AType是值類型,則分配了多少內存;而如果AType是引用類型時,又分配了多少內存?

      我們的分析如下:根據CRL的內存機制,我們知道如果ATpye為Int32類型,則表示其元素是值類型,而數組本身為引用類型,myType將保存指向托管堆中的一塊大小為4×10byte的內存地址,并且將所有的元素賦值為0;而如果AType為自定義的引用類型,則會只做一次內存分配,在線程的堆棧創建了一個指向托管堆的引用,而所有的元素被設置為null值,表示為空。 

      未完,下回即將發布。。。


       

      參考文獻

      (USA)Jeffrey Richter, Applied Microsoft .NET Framework Programming

      (USA)David Chappell, Understanding .NET


      廣而告之

      本文有些長,因此分兩回來展開。我們已經分析了類型的內存機制,接下來就該著重于類型的實際應用領域了,因此在下回中我們會從[通用規則與區別]、[實例分析]、[應用場合]、[類型比較]等幾個方面來著重展開,希望給大家以幫助,對于表達有謬或者理解有誤的地方還望不吝賜教,本人將不勝感激。

      To be continue soon ...   

      溫故知新

      [開篇有益]

      [第一回:恩怨情仇:is和as]

      [第二回:對抽象編程:接口和抽象類]

      [第三回:歷史糾葛:特性和屬性]

      [第四回:后來居上:class和struct]

      [第五回:深入淺出關鍵字---把new說透]

      [第六回:深入淺出關鍵字---base和this]

      [第七回:品味類型---從通用類型系統開始]

      ?2007 Anytao.com

      原創作品,轉貼請注明作者和出處,留此信息。

      本貼子以現狀提供且沒有任何擔保,同時也沒有授予任何權利。
      This posting is provided "AS IS" with no warranties, and confers no rights.

       

      posted @ 2007-05-23 01:01  Anytao  閱讀(29173)  評論(92)    收藏  舉報
      主站蜘蛛池模板: 欧美成人精品一级在线观看| 久久综合老鸭窝色综合久久| 人妻18毛片A级毛片免费看| 影音先锋在线资源无码| 成人自拍短视频午夜福利| 久久精品国产亚洲av熟女| 国产农村激情免费专区| 亚洲成av人片无码迅雷下载| 国产精品会所一区二区三区| 国产粉嫩美女一区二区三| 亚洲国产日韩一区三区| 精品人妻一区二区| 国产欧美日韩另类精彩视频| 亚洲精品无amm毛片| 国产精品视频一品二区三| 少妇高潮喷水久久久影院| 中文字幕乱码在线播放| www久久只有这里有精品| 国产女高清在线看免费观看| 国内精品伊人久久久久av| 国产精品一区二区黄色片| 精品2020婷婷激情五月| 人妻少妇无码精品专区| 亚洲伊人久久综合成人| 亚洲午夜理论无码电影| 崇明县| 色综合视频一区二区三区| XXXXXHD亚洲日本HD| 亚洲精品久久久久国色天香| 在线播放国产精品三级网| 久久99精品久久久久久齐齐| 国产成人一区二区不卡| 亚洲av伊人久久综合性色| 黄色三级亚洲男人的天堂| 精品91在线| 中文字幕国产精品自拍| 亚洲精品国产av成拍色拍个| 性一交一乱一乱一视频| 麻豆亚洲精品一区二区| 白银市| 国产精品一二三区蜜臀av|