2011-11-23 28 views
16

假設someClass是在C#定義的一些方法int doSomething(void)一個類,並且爲了簡單起見,提供一個構造沒有參數。然後,在C#中,實例必須在GC堆上創建:現在困惑:在C實例創建C#類的++

someClass c;     // legit, but only a null pointer in C# 
// c->doSomething()   // would not even compile. 
c = new someClass();   // now it points to an instance of someclass. 
int i = c->doSomething();  

,如果someClass被編譯到一些NET庫,你還可以在C++/CLI中使用它:

someClass^ cpp_gcpointer = gcnew someClass(); 
int i = cpp_gcpointer->doSomething(); 

那簡單!漂亮!這當然假定對.Net庫的引用已被添加到項目中並且已經做出相應的使用聲明。

這是我的理解,這是精確的C++/CLI相當於以前的C#示例(凝結成一條線,這是不是我感興趣的點)。正確? (對不起,我是新來的話題)

在C++中,然而,也

someClass cpp_cauto;    // in C++ declaration implies instantiation 
int i = cpp_cauto.doSomething(); 

是有效的語法。出於好奇,我今天試了這個。看着我的一位同事願意打賭它甚至不會編譯。他會輸掉賭注。 (這仍然是C#程序集中的類)。實際上它也產生與前面例子中的代碼相同的結果i

也很漂亮,但是 - 嗯 - 究竟是什麼,這裏創造了什麼?我的第一個猜測是,在我的背後,.Net動態地在gc堆上創建一個實例,並且cpp_auto是這個對象的某種包裝,表現得像someClass類的實例那樣合成。但後來我發現這個頁面

http://msdn.microsoft.com/en-us/library/ms379617%28v=vs.80%29.aspx#vs05cplus_topic2

本頁面似乎在告訴我,(至少,如果SomeClass的是一個C++類)cpp_auto的堆棧,在實際創建它,據我所知,是你在古典C++中獲得的行爲是一樣的。而你在C#中無法做到的事情(你不能,可以嗎?)。我想知道的是:C#程序集中的實例是否也在堆棧中創建?你可以用C++生成.Net二進制文件,但是你不能在C#中創建堆棧上的類實例嗎?這可能甚至可能會給你一個perfomance增益:-)?

親切的問候,

托馬斯

回答

12

link you referenced解釋對此進行了詳細:

C++/CLI允許你採用堆棧語義引用類型。這意味着您可以使用爲堆棧中的對象分配預留的語法來引入引用類型。編譯器將負責爲您提供您期望從C++獲得的語義,並在封面下通過實際在託管堆上分配對象來滿足CLR的要求。

基本上,它仍然使一個句柄託管堆上引用類型,但是當它超出範圍自動爲你調用Dispose()IDisposable實現。

但是,對象實例仍然通過gcnew(置於託管堆上)有效分配並由垃圾收集器收集。這也是詳細解釋:

當d超出範圍,其Dispose方法將被調用以允許其資源被釋放。同樣,由於對象實際上是從託管堆中分配的,因此垃圾收集器將在自己的時間內處理它。

基本上,這一切都由編譯器處理,使代碼看起來像標準C++堆棧分配類一樣工作,但它其實只是一個編譯器技巧。生成的IL代碼仍在執行託管堆分配。

+0

Ouch。所以我沒有意識到這一點就找到了答案。感謝您指出這一點給我:-) – Thomas

+0

@Thomas沒問題。這是一個很大的頁面 - 你必須知道在那裏尋找什麼來尋找關於編譯器技巧的討論;) –

+0

再次感謝,但是,你看,這不是因爲它是一個大頁面。關鍵是我只有在你向我指出它確實回答了我的問題之後,才瞭解引用。但也許這只是初學者的無知。然後,當然,無知是幸福的:-) – Thomas