2017-10-07 181 views
1

感謝您的關注。我是一些VS2013代碼的新手,它是C++加上一些微軟特定擴展的混合體。該代碼有像將非託管/非託管成員添加到託管類

ref class Foo { 
    Bar^ bar_; // somewhere else, bar_ = gcnew Bar... 
}; 

類現在我需要添加一個託管成員,從網上搜索好像我可以做

ref class Foo { 
    Bar^bar_; 
    Unmanaged* ptr_; // somewhere else, ptr = new Unmanaged(); 
    ~Foo() { 
     this->!Foo(); 
    } 
    !Foo() { 
     delete ptr_; 
     // do I need anything to deal with bar_? 
    } 
}; 

的問題是:

1)這是終結者/析構者的路要走嗎?

2)我是否需要爲bar_寫入任何額外的內容,現在我明確寫了終結器/析構函數?

3)有沒有更乾淨的方法來做到這一點?

回答

3

1)是這個終結器/析構函數的路要走嗎?

是的。

2)我是否需要寫什麼額外的bar_

沒有什麼,從片段明顯。但是如果Bar類是一次性的,那麼你可能應該在析構函數中加上delete bar_;。不是終結者。而且,如果您將引用傳遞給其他代碼,則不能確保該引用是最後一個仍在使用Bar對象的引用。

3)有沒有更乾淨的方法來做到這一點?

不,還有其他辦法。例如,你可以考慮不要添加析構函數。有人給出了使用該類的代碼調用它的負擔。通常這會是C#或VB.NET代碼,它將不得不使用using語句或顯式調用Dispose()。請記住,他們經常忘記。或者沒有一個好的方法來稱呼它。

如果這樣的代碼不會創建大量的Foo實例,並且Unmanaged類僅僅使用了一點內存,那麼終結器就足夠好了。或者,如果Foo對象預期會在應用程序的整個生命週期中生存下來,這很常見,那麼處置就毫無意義。即使它使用了大量的內存,GC :: AddMemoryPressure()也是一個不錯的選擇。使您的課程更易於使用。

你可以考慮將Unmanaged指針包裝在它自己的類中,這樣Foo就不再需要終結器了。按照.NET中SafeHandle類的模式,SafeBuffer是最接近的匹配項。然而,在C++/CLI包裝中,這往往是矯枉過正的,delete故障尤其不是你想要隱藏的。

但是你已經完成了工作。

+0

謝謝@ hans-passant!自從我已經是純粹的C++,但是新到VS2013之後,還有一個跟進。我如何檢查課程是否是一次性的?他們在宣言中是否都很明顯?我還看到像POD('bool'等),'array ^'和'String ^'之類的東西,例如我無法獲得'ref class array'的源碼? – hahaha

+1

當它實現IDisposable接口。對象瀏覽器可以告訴你,一個。 POD永遠不會。 –