日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

          歡迎訪問 生活随笔!

          生活随笔

          當前位置: 首頁 > 编程语言 > asp.net >内容正文

          asp.net

          【转】[你必须知道的.NET] 第八回:品味类型---值类型与引用类型(上)-内存有理...

          發布時間:2025/3/15 asp.net 31 豆豆
          生活随笔 收集整理的這篇文章主要介紹了 【转】[你必须知道的.NET] 第八回:品味类型---值类型与引用类型(上)-内存有理... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

          引用自:http://www.cnblogs.com/anytao/category/155694.html

          作者:Anytao

          ?

          本文將介紹以下內容:

          • 類型的基本概念?

          • 值類型深入

          • 引用類型深入

          • 值類型與引用類型的比較及應用

          ?

          1.?引言

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

          2. 一切從內存開始

          2.1 基本概念

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

          ?

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

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

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

          ??

          2.2 內存深入

          2.2.1. 內存機制

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

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

          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說透? 的論述,在此不做進一步描述。而我們在此強調的是myStructmyClass兩個變量在內存分配方面的區別,還是以一個簡明的圖來展示一下:

          ?

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

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

          • 值類型變量做為局部變量時,該實例將被創建在堆棧上;而如果值類型變量作為類型的成員變量時,它將作為類型實例數據的一部分,同該類型的其他字段都保存在托管堆上,這點我們將在接下來的嵌套結構部分來詳細說明。

          • 引用類型變量數據保存在托管堆上,但是根據實例的大小有所區別,如下:如果實例的大小小于85000Byte時,則該實例將創建在GC堆上;而當實例大小大于等于85000byte時,則該實例創建在LOHLarge 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的內存機制,我們知道如果ATpyeInt32類型,則表示其元素是值類型,而數組本身為引用類型,myType將保存指向托管堆中的一塊大小為4×10byte的內存地址,并且將所有的元素賦值為0;而如果AType為自定義的引用類型,則會只做一次內存分配,在線程 的堆棧創建了一個指向托管堆的引用,而所有的元素被設置為null值,表示為空。?


          轉載于:https://www.cnblogs.com/czh-liyu/archive/2008/10/15/1311635.html

          總結

          以上是生活随笔為你收集整理的【转】[你必须知道的.NET] 第八回:品味类型---值类型与引用类型(上)-内存有理...的全部內容,希望文章能夠幫你解決所遇到的問題。

          如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。