C#託管代碼與非託管代碼(摘)

什麼是託管代碼(managed code)?c++

      託管代碼是一microsoft的中間語言(IL),他主要的做用是在.NET   FRAMEWORK的公共語言運行庫(CLR)執行代碼前去編譯源代碼,也就是說託管代碼充當着翻譯的做用,源代碼在運行時分爲兩個階段:       1.源代碼編譯爲託管代碼,(因此源代碼能夠有不少種,如VB,C#,J#)       2.託管代碼編譯爲microsoft的平臺專用語言。程序員

      編譯器把代碼編譯成中間語言(IL),而不是能直接在你的電腦上運行的機器碼。中間語言被封裝在一個叫程序集(assembly)的文件中,程序集中包含了描述你所建立的類,方法和屬性(例如安全需求)的全部元數據。你能夠拷貝這個程序集到另外一臺服務器上部署它。編程

      託管代碼在公共語言運行庫(CLR)中運行。這個運行庫給你的運行代碼提供各類各樣的服務,一般來講,他會加載和驗證程序集,以此來保證中間語言的正確性。當某些方法被調用的時候,運行庫把具體的方法編譯成適合本地計算機運行的機械碼,而後會把編譯好的機械碼緩存起來,以備下次調用。(這就是即時編譯)隨着程序集的運行,運行庫會持續地提供各類服務,例如自動垃圾回收、運行庫類型檢查和安全支持等。這些服務幫助提供獨立於平臺和語言的、統一的託管代碼應用程序行爲。緩存

      Visual Basic .NET和C#只能產生託管代碼。若是你用這類語言寫程序,那麼所產生的代碼就是託管代碼。若是你願意,Visual C++ .NET能夠生成託管代碼。當你建立一個項目的時候,選擇名字是以.Managed開頭的項目類型。例如.Managed C++ application。安全

什麼是非託管代碼(unmanaged code)?服務器

      非託管代碼就是在Visual Studio .NET 2002發佈以前所建立的代碼。例如Visual Basic 6, Visual C++ 6, 最糟糕的是,連那些依然殘存在你的硬盤中、擁有超過15年曆史的陳舊C編譯器所產生的代碼都是非託管代碼。託管代碼直接編譯成目標計算機的機械碼,這些代碼只能運行在編譯出它們的計算機上,或者是其它相同處理器或者幾乎同樣處理器的計算機上。非託管代碼不能享受一些運行庫所提供的服務,例如安全和內存管理等。若是非託管代碼須要進行內存管理等服務,就必須顯式地調用操做系統的接口,一般來講,它們會調用Windows SDK所提供的API來實現。就最近的狀況來看,非託管程序會經過COM接口來獲取操做系統服務。app

      跟Visual Studio平臺的其餘編程語言不同,Visual C++能夠建立非託管程序。當你建立一個項目,而且選擇名字以M FC,ATL或者Win32開頭的項目類型,那麼這個項目所產生的就是非託管程序。編程語言

區別:函數

     一、託管代碼是一種中間語言,運行在CLR上;工具

          非託管代碼被編譯爲機器碼,運行在機器上。

     二、託管代碼獨立於平臺和語言,能更好的實現不一樣語言平臺之間的兼容;

          非託管代碼依賴於平臺和語言。

     三、託管代碼可享受CLR提供的服務(如安全檢測、垃圾回收等),不須要本身完成這些操做;

          非託管代碼須要本身提供安全檢測、垃圾回收等操做。

      託管代碼就意味着託管數據?答案是否認的。

      對於Visual Basic和C#來講,生活是簡單的,由於你沒有其它選擇。當你在那些語言裏面聲明一個類,那麼這個類的實例會在託管堆中被建立,垃圾收集器(GC)會幫咱們管理這些對象的回收。可是在Visual C++中,你有另外一個選擇。即便你正建立一個託管程序,你能夠決定哪些類是託管類型,哪些類是非託管類型的。

這就是非託管類型:

class Foo {    private:       int x;    public:       Foo(): x(0){}       Foo(int xx): x(xx) {} };

這就是託管類型

__gc class Bar {    private:       int x;    public:       Bar(): x(0){}       Bar(int xx): x(xx) {} };

      他們惟一的區別就是類Bar的定義中有__gc關鍵字。這個關鍵字會給代碼帶來巨大的區別。

      託管類型是能夠被垃圾回收器所回收的。他們必需要用關鍵字new來建立,永遠都不會在棧中出現。因此下面這行代碼是合法的:

      Foo f;

      可是這一行代碼就是非法的:

      Bar b;

      若是我在堆中建立一個Foo對象,那麼我必需要負責清理這個對象:

      Foo* pf = new Foo(2);       // . . .       delete pf;

      C++編譯器實際上會用兩個堆,一個託管堆和一個非託管堆,而後經過對new操做符的重載來實現對建立不一樣類型類的實例,分配不一樣的內存。若是我在堆裏面建立一個Bar實例,那麼我能夠忽略它。當沒有其餘代碼在使用它的時候,垃圾回收器會自動清理這個類,釋放其佔用的資源。 對於託管類型會有一些約束:它們不能實現多重繼承,或者繼承於非託管類型;它們不能用friend關鍵字來實現私有訪問,它們不能實現拷貝構造函數。因此,你有可能不想把你的類聲明爲託管類型。可是這並不意味着你不想讓你的代碼成爲託管代碼。在Visual C++中,你能夠選擇。

      託管代碼與非託管代碼的性能比較       基本上每一個人都知道的是,全部.Net語言都將被編譯成爲一個叫作IL彙編的中間語言。可是計算機是如何執行這個中間代碼的,倒是不少人不知道,甚至理解錯誤了的。       JIT是.NET程序運行的重要部件之一,全稱是即時編譯器。不少人(絕對不是少數,問了不少c++程序員,10個有9個這種想法)都覺得JIT其實就是跟Java VM差很少的東西,是一個Interpreter,在運行時讀取IL彙編代碼,而後模擬成x86代碼(也就是俗稱的虛擬機)。可是事實上,.NET使用的是更爲高級的技術。 .Net程序被加載入內存之後,當某段IL代碼被第一次運行的時候,JIT編譯器就會將這段IL代碼,所有編譯成本地代碼,而後再執行。這也就是爲何.NET程序第一次運行都啓動很慢的緣由! 隨.NET庫,微軟還附帶了一個工具,能夠事先將.NET程序全部的IL代碼都編譯成本地代碼並保存在緩存區中,這樣一來,這個程序就跟c++編譯的如出一轍了,沒有任何區別,運行時也能夠脫離JIT了(這裏不要混淆了,這裏不是說能夠脫離.NET庫,而是說不須要在進行即時編譯這個過程了)。因此,請不要將.NET和Java混爲一談,兩個的運行效率根本不是一個等級的!

     JIT的優化指的是能夠針對本地CPU,在編譯時進行優化。傳統程序在編譯時,爲了保證兼容性,一般使用最通用的指令集(好比古老的386指令集)來編譯。而JIT知道CPU的具體類型,能夠充分利用這些附加指令集進行編譯,這樣的性能提高是很可觀的。