2014-10-30 122 views
0

通常,在C++的指針,如果一個人創建一個動態對象傳遞到函數作爲參數,將它做類似垃圾收集器,用於託管C++

Object *myObj = new Object; 
someFunction(myObj); 
delete myObj; 
myObj = nullptr; 

而非

someFunction(new Object); 

爲了不泄漏內存。現在假設我正在創建一個垃圾收集對象;這個規則是否仍然適用,或者垃圾回收器是否真的能夠從函數調用中創建的內存中刪除一個動態創建的對象,如下所示?

someFunction(gcnew Object); 
+0

不應該分配是否在()之間。 – deviantfan 2014-10-30 18:59:47

+0

您不再需要跟蹤您使用託管C++創建的對象。即使您在()中創建了對象,您的C++/CLI對象也會按垃圾收集器的預期收集和銷燬。 – ArthurCPPCLI 2014-10-31 08:18:39

回答

3
someFunction(gcnew Object); 

好的,沒關係。該對象將無法存活很長時間,如果某些功能沒有以其他方式存儲該引用,則下一代#0集合可能會將其摧毀。您可以聲明一個變量,但這沒有意義,它將在運行時由抖動優化器刪除,並且最終會得到完全相同的代碼。


要記住這一點很重要,但是delete運算符仍然存在於C++/CLI中。但是,完全是與它在本地C++中的不同。它調用一個類的IDisposable :: Dispose()實現方法。這提供了「確定性破壞」,就像在C++中一樣。不是很合適的話,它確實是確定性清理。該接口由任何託管類實現,該託管類存儲「昂貴」的操作系統資源,這種類型在垃圾收集器清理之前不想掛起。

Boilerplate示例是System :: Drawing :: Bitmap類。一個非常小的類,它是大塊地址空間和(可能)被鎖定的文件的包裝。你想確保在你不再需要它時處理它。你可以寫這樣的代碼是這樣的:

void dosomething() { 
    Bitmap^ bmp = gcnew Bitmap("foo.png"); 
    drawBitmap(bmp); 
    delete bmp; 
} 

但是,這是不正確的代碼,它不是異常安全的。 刪除drawBitmap引發異常時,運營商呼叫將被繞過。不是世界末日btw,這實際上並沒有造成泄漏,因爲GC最終會將清理乾淨。然而,不愉快的,所以C++/CLI設計師與本地C++ RAII模式的仿真,叫想出了「堆棧語義」,在C++/CLI:

void dosomething() { 
    Bitmap bmp("foo.png"); // NOTE: no^hat 
    drawBitmap(bmp); 
} // <=== bmp is disposed here 

這應該熟悉任何C++程序員:)

0

當您的應用程序中沒有更多的引用時,被管對象全部被垃圾收集器銷燬。

在你的情況下,如果你的函數沒有在其他地方分配你的對象,它將被緩衝,一旦函數返回就被垃圾收集。

0

是的,因爲正常運行的垃圾回收器會在分配給該內存的變量超出範圍時刪除動態分配的內存。例如,在Java中,可以這樣說:

button.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent e) 
    { 
     // do something. 
    } 
}); 

並且「ActionListener()」在超出作用域時被刪除。我只提到Java,因爲它的垃圾收集屬性,並意識到這是一個C++問題。我只是用它來解釋一個概念。