2010-08-07 52 views
24

這裏是我有一個示例代碼:刪除在C++的對象

void test() 
{ 
    Object1 *obj = new Object1(); 
    . 
    . 
    . 
    delete obj; 
} 

我在Visual Studio中運行它,並且它崩潰在與線「刪除OBJ;」。 這不是通常的方式來釋放與對象關聯的內存嗎? 我意識到它會自動調用析構函數......這是正常的嗎?


下面的代碼片段:

if(node->isleaf()) 
    { 
     vector<string> vec = node->L; 
     vec.push_back(node->code); 
     sort(vec.begin(), vec.end()); 

     Mesh* msh = loadLeaves(vec, node->code); 

     Simplification smp(msh); 

     smp.simplifyErrorBased(errorThreshold); 

     int meshFaceCount = msh->faces.size(); 

     saveLeaves(vec, msh); 

     delete msh; 
    } 

loadleaves()是從磁盤中讀取一個網格,創建一個Mesh對象,並返回它的功能(想vecnode->code是關於剛剛信息文件被打開)

我應該刪除delete msh;行嗎?

+3

讓我們看看你的課堂是什麼樣子。你的析構函數可能有問題。 – TheFuzz 2010-08-07 02:56:00

+0

下面提到的'loadLeaves'函數是否在堆上分配對象?或者它是否返回本地地址或類似的地址?記住,你只能'刪除'你'新'...​​ – 2010-08-07 05:44:29

+0

確保析構函數不是私有的! – Vaibhav 2013-08-08 08:29:56

回答

32

這是不是正常的方式來釋放與對象關聯的內存嗎?

這是管理動態分配內存的常用方法,但這不是一個好方法。這種代碼很脆弱,因爲它不是異常安全的:如果在創建對象和刪除對象之間引發異常,則會泄漏該對象。

使用智能指針容器,您可以使用它來獲取作用域綁定資源管理(通常稱爲resource acquisition is initialization或RAII),這會更好。

自動資源管理的一個例子:

void test() 
{ 
    std::auto_ptr<Object1> obj1(new Object1); 

} // The object is automatically deleted when the scope ends. 

根據你的使用情況,auto_ptr可能無法提供你所需要的語義。在這種情況下,您可以考慮使用shared_ptr。至於爲什麼當你刪除對象時你的程序崩潰了,你沒有給出足夠的代碼給任何人以確定的方式回答這個問題。

2

如果它在delete行崩潰,那麼你幾乎肯定會以某種方式損壞堆。由於您提供的示例沒有錯誤,因此我們需要查看更多代碼來診斷問題。

也許你在堆上有一個緩衝區溢出,這會破壞堆結構,甚至像「雙免費」(或在C++的情況下「雙刪除」)那樣簡單。另外,正如The Fuzz指出的那樣,你的析構函數也可能有錯誤。

是的,這是完全正常的,並且期望delete調用析構函數,這實際上是它的兩個目的之一(調用析構函數然後釋放內存)。

3

這不是通常的方式來釋放與對象關聯的內存嗎?

是的。

我意識到它會自動調用析構函數......這是正常的嗎?

Yes

確保你沒有double delete你的對象。

+1

那麼,爲什麼這是正常的? 由於它是一個指針變量,這是如何正常自動刪除? 發生了什麼是首先我刪除對象,然後到達行'}'它再次調用析構函數,這會導致問題。 我的問題是爲什麼它會自動調用析構函數? 如果這是正常的,那麼爲什麼人們在這種情況下刪除一個對象? – Nima 2010-08-07 02:58:46

+1

閱讀這些:http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.9和http://www.parashift.com/c++-faq-lite/freestore-mgmt.html# faq-16.9 '然後析構函數Fred ::〜Fred()將自動*在你刪除時被調用......' 向我們展示完整的代碼。 – 2010-08-07 03:06:35

6

你的代碼的確使用正常的方式來創建和刪除一個動態對象。是的,這完全正常(並且確實由語言標準保證!)delete將調用對象的析構函數,就像new必須調用構造函數一樣。

如果沒有實例Object1直接,但一些子類上,我想提醒大家,任何類打算從繼承必須有一個虛擬析構函數(以便正確的子類的析構函數可以在類似的情況下被調用到這個) - 但是如果你的示例代碼確實代表了你的實際代碼,這不可能是你目前的問題 - 必須是別的東西,也許在你沒有展示給我們的析構函數代碼中,或者是一些堆 - 你沒有在該功能中顯示的代碼或它所調用的代碼...?

順便說一句,如果你總是要在退出實例化它的函數之前刪除該對象,那麼使該對象變爲動態沒有意義 - 只需將它聲明爲本地(存儲類auto,就像默認)所說功能的變量!

1

saveLeaves(vec,msh);
我假設需要msh指針,並把它放在vec裏面。由於msh只是一個指向內存的指針,如果你刪除它,它也會被刪除。