Pure C++(中文版)

來源:互聯網
上載者:User

Pure C++ 專欄...

原著:Stanley B. Lippman
翻譯:coffer

原文出處:Pure C++:Hello, C++/CLI

  歡迎來到我在MSDN雜誌主持的第一個專欄!實際上,我以前寫過第一個專欄,其內容完全不同——講的是Visual Studio 2005中新的泛型程式設計支援。但回想起來,我 覺得那篇文章留下了太多的未解答問題。因此我另闢蹊徑開設這個專欄,以便提供一個我的團隊在開發 Visual C++ 2005 中的 C++/CLI 方面的概觀。由此我還將寫一些有關.NET泛型程式設計的專欄。不要忘了本專欄是基於預覽版的,因此有些內容可能會改變。

什麼是C++/CLI?

  C++/CLI描繪的是一種多元組合,此處的 C++ 當然是指 Bjarne Stroustrup 在 Bell 實驗室發明的C++程式設計語言。它支援速度和執行 檔案的大小都得到最佳化的靜態物件模型。但除了堆記憶體配置以外,它不支援運行時程式對對象的更改。它允許對底層機器進行無限制的訪問,但對於正在啟動並執行程式中的活動類型、以及相關的程式基礎構造,它的訪問能力卻非常有限、或者根本就不可能。我在微軟的同事 Herb Sutter,也是C++/CLI的主架構師,認為C++是一個混凝土語言。
  “CLI”即通用語言基礎結構(Common Language Infrastructure),這是一個支援動態組件編程模型的多層架構。在許多方面,它所表示的物件模型和C++的完全相反。它是一個運行時軟體層 ,一個虛擬執行系統,運行在應用程式和底層作業系統之間。對底層機器的訪問受到相當嚴格的限制。支援對運行中程式的活動類型以及關聯程式的基礎構造 進行存取——發現和建構。斜線“/”表示 C++ 和 CLI 之間的一種綁定(binding),有關這種綁定的細節構成本專欄的常規主題。
  所以,對於“什麼是C++/CLI?”這個問題第一個最近似的答案是:它是靜態C++物件模型到動態CLI元件物件模型的一種綁定, 簡言之,它就是你如何用C++進行.NET編程,而不是用C#或Visual Basic.NET。象C#和CLI自己一樣,C++/CLI正在經曆 ECMA(歐洲電腦製造商協會) 標準化並最終要經曆ISO標準認證。
  通用語言執行平台(CLR)是微軟版的CLI,專門用於 Windows 作業系統,同樣,Visual C++ 2005是C++/CLI 的實現。
  第二個近似答案是:我覺得C++/CLI在C++內整合.NET編程模型與以前貝爾實驗室在當時的C++中用樣板集成泛型程式設計一樣有異曲同工之處。兩種情況中,你在現有C++程式碼程式庫上的投資以及你現有的C++專業技術都得到保護。這是C++/CLI設計的一個基本 要求。

學習C++/CLI

  一種C++/CLI語言的設計有三個層面,這三個層面也適用於所有語言:語言層文法到公用類型系統(CTS) 的映射;選擇為程式員直接操作而公開的底層CLI基主要組織結構 的詳細程度;以及選擇要提供的超越CLI直接支援的附加功能。
  第一個層面是所有CLI語言在很大程度上都共有的,第二個層面和第三層面是某一CLI語言區別於其它語言的地方。根據所要解決的問題,你可以選擇某一 種語言,也可以將多種CLI語言結合起來。學習C++/CLI語言需要掌握這三個設計層面。

怎樣將C++/CLI 映射到CTS?

瞭解底層CTS 對學習C++/CLI非常有協助,它主要包括三個常規類類型:

  • 多態參考型別,其用於所有的類繼承;
  • 非多態實值型別,其用於實現需要運行時效率的具體類型,如數字類型;
  • 抽象介面類型,其用於定義一個實現該介面的一組參考型別或實值型別共同使用的公用操作集;

  在設計方面,雖然CTS到一組內建的語言類型的映射對於所有CLI語言來說都是共同的,當然,每一種CLI語言的文法各不相同。例如,在C#中,我們可以 這樣來定義一個抽象基類 Shape,從這個類派生特定的幾何模型對象。

abstract class Shape { ... } // C#

而在C++/CLI中,可以象下面這樣寫,以表示完全相同的底層參考型別:

ref class Shape abstract { ... }; // C++/CLI

  在底層 IL(中繼語言)中,以上兩種聲明以完全相同的方式表示。同樣,在C#中,我們可以用下面的代碼來定義一個具體的 Point2D 類 :

struct Point2D { ... } // C#

而在C++/CLI中寫成:

value class Point2D { ... }; // C++/CLI

藉助 C++/CLI 支援的類類型家族表現了一種本機方式的 CTS 整合。它確定了你的文法選擇,例如:

class native {};value class V {};ref class R {};interface class I {};

CTS 也支援枚舉類類型,其行為方式與本機枚舉稍微有些區別,C++/CLI對二者都提供支援:

enum native { fail, pass }; enum class CLIEnum : char { fail, pass}; 

同樣,CTS支援其自己的數群組類型,其行為也與本機數群組類型有一定差別,微軟同樣對二者提供支援:

int native[] = { 1,1,2,3,5,8 }; array<int>^ managed = { 1,1,2,3,5,8 };

  那種認為任何一種 CLI 語言比另一種語言更接近或幾乎就是到底層CLI的映射是不精確的。相反,每一種CLI語言都只是表達了自己對底層CLI物件模型的一種 見解。在下一節你將更清楚地看到這一點。

CLI 的細節標準

  在設計CLI語言時必須考慮的第二個設計層面是要將什麼程度的底層CLI實現模型結合到該語言中。這個語言解決什麼樣的問題?要解決這些問題必須要什麼樣的工具? 此外,該語言很可能吸引哪一類程式員?
下面,我們利用發生在託管堆中的實值型別問題。在許多情況下,實值型別可以在託管堆中找到自己:

  • 通過隱式的框入/框出操作(boxing)——當實值型別的某個執行個體被賦值給一對象時,或者通過某個未被改寫的實值型別調用一個虛擬方法時;
  • 當實值型別被當作為引用類類型的成員時;
  • 當實值型別被當作CLI數組元素儲存時;

是否允許程式員處理這種實值型別地址是設計CLI語言時必須要解決的問題。

存在的問題?

  位於託管堆中的任何對象在記憶體回收行程進行清掃收縮的過程中都有可能遭遇重新分配,指向這些對象的任何指標必須被追蹤並在運行時得到更新,而程式員 無法自己手動追蹤它們,因此,如果你被允許用某個可能在託管堆中的實值型別的地址,那麼除了本機指標外,還需要一個追蹤形態的指標。
  到底該怎樣去權衡呢?一方面,需要考慮簡潔和安全。直接引入對一個或一組追蹤指標的支援會使語言變得更複雜。如果不提供這種支援,由於所需的複雜程度降低,從而可以找到的程式員人群就會增加。此外,允許程式員訪問這些生命期短暫的實值型別,則增加了程式員出錯的可能性。她經意或不經意地對記憶體做一些危險動作。不支援追蹤指標,可以潛在地建立較安全的運行時環境。
  另一方面,必須考慮效率和靈活性。每次將實值型別賦值給相同的對象,該值都會發生新的框入/框出操作。允許訪問這種經過框入/框出操作的實值型別 ,就允許在記憶體中進行更新操作,這樣便可能提供重要的效能改進。沒有某種形式的追蹤指標,你將無法用指標演算法遍曆CLI數組,這意味著CLI數組將不能 融入STL(標準模板庫)中的迭代器模式,也無法與泛型演算法協同工作。允許訪問框入/框出實值型別將會大大提高設計的靈活性。

在C++/CLI 中,微軟選擇提供一系列在託管堆中處理實值型別的定址模式:

int ival = 1024;int^ boxedi = ival; array<int>^ ia = gcnew array<int>{1,1,2,3,5,8};interior_ptr<int> begin = &ia[0];value struct smallInt { int m_ival; ... } si;pin_ptr<int> ppi = &si.m_ival;

  典型的 C++/CLI 開發人員是一個經驗豐富的系統程式員,其任務是提供底層架構以及作為基礎的核心應用,以此為基礎來構建未來。她必須解決延展性和效能相關的問題,並且必須從系統一級來看待底層 CLI。某種 CLI 語言的細節標準反映了其程式員的面貌。
  複雜性本身並不是對品質的否定,人類生命比單核細胞複雜得多,這當然不是一件壞事,然而,當單一概念的表達變得複雜化以後,這常常被認為是一件壞事。在C++/CLI中,CLITeam Dev已經 嘗試提供一種優雅的方式來表達一個複雜的主體。

附加功能

  第三個設計層面是特定語言層功能要超過被CLI直接支援的功能,這樣就需要建立一種語言層支援與CLI底層實現模型之間的映射。 在某些情況下,這是做不到的,因為該語言無法調解CLI的行為,在基類的建構函式和解構函式中解決虛函數便是例子。為了在這種情況中反映ISO-C++語義,需要在每個基類的建構函式和解構函式中 重新安排虛表。這是不可能的,因為虛表操作是由運行時託管的,而非單獨的語言託管。

因此,這一設計層面是優越性和可行性的折中。C++/CLI 提供的附加功能主要有三個方面:

  • 參考型別的資源擷取(Resource Acquisition)形式是Initialization(RAII), 尤其是為被稱作佔據稀有資源的記憶體回收類型確定性終止化(deterministic finalization)提供一個自動化的機制;
  • 與C++拷貝建構函式和拷貝賦值操作符相關的深度拷貝語義形式,但它不能擴充到實值型別;
  • 除了 CLI泛型機制之外——這原來是我第一個專欄的主題,還為CTS類型提供C++模板的直接支援,另外,還提供用於 CLI 類型的 STL 可驗證版本;

  讓我們看一個簡單的例子:確定性終止化問題。與對象關聯的記憶體被記憶體回收行程回收之前,若存在與之相關連的 Finalize 方法,該方法將會被調用。你可以把 該方法看作是一種超級解構函式,因為它不依賴於該對象程式的生命期,它被稱為終止化。調用 Finalize 方法的時間,甚至是否調用它是未定義的。這就是記憶體回收行程不確定的終止化操作含義之所在。
  不確定性終止化在進行動態記憶體管理時可以很有效地工作,當可用記憶體空間嚴重不足時,記憶體回收行程會發揮作用並解決問題。但是當對象涉及的是某些重要資源,比如資料庫連接、某種 類型的鎖、本地堆記憶體時,不確定性終止化的表現卻不盡人意。在這種情況下,最好是儘快釋放不再需要的資源。目前CLI採用的解決辦法是:某個類在其 IDisposable 介面的 Dispose 方法中釋放資源,這裡的問題是 Dispose 需要顯式調用,因此它不可能被執行。
  C++的基本設計模式是前述的資源擷取(Resource Acquisition )即初始化(Initialization),它意味著類通過建構函式 擷取資源,相反,通過解構函式來釋放資源。在類對象的生存期內是自動管理的。
以下是參考型別釋放資源的過程:

  • 用解構函式壓縮在釋放資源過程中必須的代碼;
  • 自動調用綁定到類物件存留期的解構函式;

  CLI中,參考型別的類沒有類析構的概念,因此,解構函式被映射到底層實現中另外的東西上,編譯器則在內部完成如下轉換:

  • 類具備其基類列表,從介面 IDisposable 延伸繼承;
  • 解構函式被轉換成IDisposable 的 Dispose 方法;

  這僅僅完成了一半,還需要一種解構函式的自動調用途徑。支援參考型別專用的基於堆棧的符號,也就是說其生命期與其聲明的範圍相關聯。編譯器 在內部轉換符號,在託管堆中分配引用對象。隨著範圍的終止,編譯器插入一個對 Dispose 方法的調用——使用者定義的解構函式。與該對象關聯的實際記憶體的回收仍然在記憶體回收行程的掌控之下。例如如 Figure 1 所示。
  C++/CLI 不僅僅是C++到管理世界的擴充,相反,它 表現了一種完全的編程範例,類似於早期多重繼承和泛型程式設計範例整合到該語言一樣,我認為這個團隊完成了一項傑出的工作。

那麼,你是如何看待 C++/CLI 的呢?
  C++/CLI代表了本地和託管編程的綜合,在這個反覆過程中,這種綜合通過即獨立而又等同的源碼級和二進位元素共同體來完成,包括混合模式( 本機和CTS類型的源碼級混合,以及本機和CIL對象檔案的二進位混合),地類型和CTS類型的混合,新增了混合本機物件和CIL對象的二進位檔案),純模式( 本機和CTS類型的源碼級混合,所有編譯過的 CIL 對象檔案),本機類(僅通過專門的封裝類才可以操控 CTS 類型),以及 CTS 類(只能以指標形式操控本機類型)。
  當然,C++/CLI 程式員也可以選擇單獨用 CLI 類型來編程,在這種方式中提供能被寄宿的可驗證代碼,比如 SQL Server 2005 中的預存程序。
  現在,回到什麼是 C++/CLI 的問題,它是進入.NET編程模型的第一道門檻,有了 C++/CLI,你不僅具備了遷移 C++ 原始碼庫的途徑,同時還可以遷移 C++ 專業技術。這讓我感覺非常愜意。

問題和建議請發送到 purecpp@microsoft.com.

作者簡介
  Stanley B. Lippman 是 Microsoft 公司 Visual C++ 團隊的架構師。從 1984 年開始他便在 Bell 實驗室與 C++ 的發明者 Bjarne Stroustrup 一起研究 C++。在此期間,他在 Disney 和 DreamWorks 製作特色動畫,同時他還是 JPL 的進階顧問以及 Fantasia 2000 的軟體技術主管。  

本文出自 MSDN Magazine 的 February 2005 期刊,可通過當地報攤獲得,或者最好是 訂閱
 

本文由 VCKBASE MTT團隊 翻譯

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.