乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      C# 值類型和引用類型的內(nèi)存管理

       昵稱10504424 2013-02-19

      本次日志,我們來重點聊一聊軟件開發(fā)過程中,如何提高性能方面的問題。這是軟件開發(fā)或研發(fā)過程中深層次的問題,這篇文章主要從內(nèi)存分配和內(nèi)存回收兩方面說明,我們軟件代碼編寫過程中,計算如何來工作的。在此你可以了解內(nèi)存管理的過程和方式,以便在以后的軟件開發(fā)中注意它、利用它。

      值類型包括:int,float,double,bool,結(jié)構(gòu),引用,表示對象實例的變量

      引用類型包括:類和數(shù)組;比較特殊的引用類型string、object

      一般情況下:值類型存儲在堆棧中(不包括包含在引用中的值類型,如類的值字段,類中的引用字段,數(shù)組的元素這些都是隨引用存儲在受管制的堆中);引用類型存儲在受管制的堆中,為什么說是受管制的堆,下面會具體來談。

      幾個概念:

      虛擬內(nèi)存:32位的計算機,每個進程擁有4G的虛擬內(nèi)存。

      受管制的堆(托管堆):受誰的管制?當然是無用單元收集器,即垃圾收集器。如何管理下面再說?

      無用單元收集器:垃圾收集器除了會壓縮托管堆、更新引用地址、還會維護托管堆的信息列表等等。

      關于值類型的存儲先看如下代碼:

      {

      int age=20;

      double salary=2000;

      }

      上面定義的兩個變量,int age,告訴編譯器需要給我分配4個字節(jié)的內(nèi)存空間來存儲age值,它是存儲在堆棧上的。堆棧屬入先進后出的數(shù)據(jù)結(jié)構(gòu),堆棧是從高位地址到低位地址存儲數(shù)據(jù)的。計算機寄存器中保持著一個堆棧指針,他總是指向堆棧最底端的自由空間地址,當我們定義一個int類型的值時,堆棧指針遞減四個字節(jié)的地址;當變量出了作用域后,堆棧指針相應的相應的遞增四個字節(jié)的地址,它只是堆棧指針的上下移動,所以堆棧的性能是相當高的。

      下面看一下引用類型的存儲,還是先看代碼:

      {

      Customer customerA;

      customerA=new Customer(); //假定Customer實例占據(jù)32個字節(jié)

      }

      上面的代碼第一行先聲明了一個Customer引用,引用的名字為customerA,在堆棧上給此引用分配存儲空間,存儲空間的大小為4個字節(jié),因為它只存儲了一個引用,這個引用所指向的才是即將存儲Customer實例的空間地址,注意此時customerA并沒有指向具體的空間,它只是分配了一個空間而已。

      第二行執(zhí)行過程中,.net環(huán)境會搜索托管堆,尋找第一個未使用的、連續(xù)的32個字節(jié)空間分配給類的實例,并設置customerA指向這段空間的頂端位置(堆的空間是從低到高使用的)。當引用變量出作用域后,堆棧中的引用會無效,當托管堆中的實例還在,直到垃圾收集器對其進行清理。

      到這里細心的讀者可能會有些疑問,是不是定義引用類型時,計算機要搜索整個堆,尋找足夠大的內(nèi)存空間來存儲對象呢?這樣會不會效率很低?如果沒有足夠大的連續(xù)的空間呢?這個就要談到“托管”了。堆是受垃圾收集器管理的,.net在執(zhí)行垃圾收集器時釋放能釋放的所有對象,并壓縮其他對象,然后把所有自由空間組合在一起移動到堆的頂端, 形成連續(xù)的塊,同時更新其他移動對象的引用。如果再有對象定義,可以很快找到合適的空間。如此看來托管堆工作方式與堆棧類似,它是通過堆指針來完成空間的分配和回收的。

      上面談了.net對內(nèi)存空間分配的管理過程和方式,接下來談一談對內(nèi)存的回收過程。談到資源的清理,不得不提到的兩個概念和三個方法。

      兩個概念為:托管資源和非托管資源。

      托管資源接受.net framework的CLR(通用語言運行時)的管理;非托管資源則不受它的管理。

      三個方法為:Finalize(),Dispose(),Close()。

      一、Finalize()為析構(gòu)方法,清除非托管資源。

      在類中定義方式:

      public ClassName{

      ~ClassName()

      {

      //清理非托管資源(如關閉文件和數(shù)據(jù)庫聯(lián)接等)

      }

      }

      它的特點是:

      1. 運行不確定性。

      它是受垃圾收集器的管理,當垃圾收集器工作時,會調(diào)用此方法。

      2. 性能開銷大。

      垃圾收集器工作方式為,對象如果執(zhí)行了Finalize()方法,垃圾收集器第一次執(zhí)行時,會把它放在一個特殊的隊列中;第二次執(zhí)行的時候才會刪除此對象。

      3. 不能顯示定義和調(diào)用,定義為析構(gòu)方法形式。

      基于以上特點,最好不要執(zhí)行Finalize()方法,除非類確實需要它或與其他兩個方法結(jié)合來用。

      二、Dispose()方法,可清除一切需要清除的資源,包括托管和非托管資源。

      定義如下:

      public void Dispose()

      {

      //清理應該清理的資源(包括托管和非托管資源)

      System.GC.SuppressFinalize(this); //這一句很重要,下面會解釋原因。

      }

      它的特點:

      1. 任何客戶代碼都應顯示調(diào)用這個方法,來釋放資源。

      2. 由于第一點的原因,一般要做一個備份,這個備份一般由析構(gòu)方法來擔任角色。

      3. 定義此方法的類,必須繼承IDisposable接口。

      4. 語法關鍵字using等同于調(diào)用Dispose(),使用using時,它是默認調(diào)用Dispose()方法。所以使用using的類也要繼承IDisposable接口。

      Dispose()方法比較靈活,在資源不需要時立即釋放。它是資源的最終處理,調(diào)用它意味著會最終刪除對象。

      三、Close()方法,暫時處置資源的狀態(tài),可能以后還會使用。一般處理非托管資源。

      定義如下:

      public viod Close()

      {

      //對非托管資源狀態(tài)的設置,如關閉文件或數(shù)據(jù)庫連接

      }

      它的特點:

      對非托管資源狀態(tài)的設置,一般是關閉文件或數(shù)據(jù)庫連接。

      下面寫一個綜合且又經(jīng)典的的例子,利用代碼演示一下各部分的作用:(為了省事,這個例子是從網(wǎng)上杜撰來的,只要說明問題就可以了,你說呢。在此應該感謝代碼原創(chuàng)者,感謝他寫了這么經(jīng)典和易懂的代碼,我們受益匪淺!)

      public class ResourceHolder : System.IDisposable

      {

      public void Dispose()

      {

      Dispose(true);

      System.GC.SuppressFinalize(this);

      // 上面一行代碼作用是防止"垃圾回收器"調(diào)用這個類中的析構(gòu)方法

      // 為什么要防止呢? 因為如果用戶記得調(diào)用Dispose()方法,那么

      // 如果用戶不記得調(diào)用呢,就讓"垃圾回收器"幫我們?nèi)?多此一舉"吧 ^_^

      // 你看不懂我上面說的不要緊,下面我還有更詳細的解釋呢!

      }

      protected virtual void Dispose(bool disposing)

      {

      if (disposing)

      {

      // 這里是清理"托管資源"的用戶代碼段。

      }

      // 這里是清理"非托管資源"的用戶代碼段。此處為析構(gòu)方法的實際執(zhí)行代碼,為了避免客戶代碼忘記顯示調(diào)用Dispose()方法,所作的備份。

      }

      ~ResourceHolder()

      {

      Dispose(false); // 這里是清理"非托管資源"

      }

      }

      如果看不明白以上代碼,一定要仔細閱讀以下解釋,很經(jīng)典,不看會后悔呦。

      這里,我們必須要清楚,需要用戶調(diào)用的是方法Dispose()而不是方法Dispose(bool),然而,這里真正執(zhí)行釋放工作的方法卻并不是Dispose(),而是Dispose(bool) ! 為什么呢?仔細看代碼,在Dispose()中,調(diào)用了Dispose(true),而參數(shù)為"true"時,作用是清理所有的托管資源和非托管資源;大家一定還記得我前面才說過,"使用析構(gòu)方法是用來釋放非托管資源的",那么這里既然Dispose()可以完成釋放非托管資源的工作,還要析構(gòu)方法干什么呢? 其實,析構(gòu)方法的作用僅僅是一個"備份"!

      為什么呢?

        本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多