2011-06-10 103 views
2

在幾乎完全使用非託管C++之後,第一次編寫managed-C++時需要注意哪些最常見的問題?Common managed C++ gotchas

+0

人們仍然使用Managed C++?我認爲大多數項目已經轉換到C++/CLI。 :-O – 2011-06-10 16:28:07

+1

一個問題就是將它稱爲託管C++(小寫m),因爲它是託管代碼,不知道在C++/CLI之前有託管C++(其中我們大部分都不會說。) – 2011-06-11 16:48:14

+1

最大的錯誤是假設它是類似於C++。先寫一些C#代碼來感受一下託管環境。 – 2011-06-11 18:50:36

回答

2

當您使用內置的IJW(It Just Works)技術將託管代理轉換爲指向函數的指針時,函數指針不包含對委託來自的對象的引用。如果您不想安排參考,則可以收集管理對象,然後在調用該函數時,您將得到一個NullReferenceException。

如果您正在製作一個採用回調的C庫,並且您想將其包裝到託管類中,您會遇到很多問題。託管類的客戶端將提供一個委託,您將其轉換爲回調。您還必須保留對委託或目標對象的引用。

這在託管C++和C++/CLI中是正確的。

+0

不是C++ - 特定的,這會影響所有.NET語言。請參閱['Marshal.GetFunctionPointerForDelegate'](http://msdn.microsoft.com/zh-cn/library/system.runtime.interopservices.marshal.getfunctionpointerfordelegate.aspx)。「代理被轉換爲一個函數指針,可以使用__stdcall調用約定傳遞給非託管代碼。 您必須手動讓代理不被垃圾收集器從託管代碼收集。垃圾收集器不會跟蹤引用非託管代碼「。 – 2011-06-11 17:42:03

1

如果你的意思是C++/CLI ...

  • 忘記通過引用傳遞參數時使用pin_ptr。與此相關,瞭解跟蹤句柄和指針之間的區別至關重要。請參閱Expert C++/CLI的第一章。
  • C++/CLI沒有C#的yield構造,在使用TestCaseSource屬性編寫單元測試和Nunit來生成測試用例數據時,我們使用它很多。這與下一個有關。
  • 實施系統:: IEnumerable是非常麻煩的。但一旦你做了一次,你有一個參考,所以它沒有那麼糟糕。
  • 理解析構函數和終結器之間的區別非常重要。對於這個討論,再次看到Expert C++/CLI
1

第4章下面是另一個疑難雜症:在對象上執行的方法不構成對對象的引用。這意味着在對象的成員方法執行期間,但在最後一次引用this之後,可能會在方法仍在執行且終結器可能觸發時清理該對象。

如果你的對象具有被終結清理或包含這樣的非託管狀態的任何其他對象的你在非託管狀態做任何計算非託管狀態,保證這些非託管計算後打電話到GC::KeepAlivethis。我現在傾向於將GC::KeepAlive附加到非託管計算對象的所有方法。

0

一個問題(剛剛拿到我):假設「析構函數只能執行一次」。由於析構函數是通過Dispose調用的,並且Dispose可能會被多次調用,所以對於C++/CLI這種假設(對於C++來說很好)並不適用。