2011-08-19 36 views
0

我有以下代碼如何刪除已解除引用的對象?

MyObject * func1() { 
    MyObject * obj = new MyObject(); 
    // lots of stuff here 
    return obj; 
} 

MyObject func2() { 
    MyObject * obj = func1(); 
    // even more stuff here 
    return *obj; 
} 

void main() { 
    MyObject obj = func2() 
} 

當我從here得到它的代碼泄漏。請問:

MyObject * func1() { 
    MyObject * obj = new MyObject(); 
    // lots of stuff here 
    return obj; 
} 

MyObject func2() { 
    MyObject * obj = func1(); 
    // even more stuff here 
    MyObject obj_r(*obj); 
    delete obj; 
    return obj_r; 
} 

void main() { 
    MyObject obj = func2() 
} 

解決了這個問題?還是有其他一些很好的解決方案?

在b4中:不,我不能從開頭引用它,因爲func1()在某些情況下返回NULL。

UPD:增加了一些評論,讓人們沒有想到我莊嚴愚蠢

+2

「func1()在某些情況下返回NULL」,但是您在不經過測試的情況下解除引用它? –

+1

當然,我做了一個檢查。我在那裏做了很多東西,我只是不想把它放在這裏,因爲它沒有關係。 – Morse

+1

確切_how_是func1返回NULL嗎?運算符'new'引發,它不返回NULL。 – Damon

回答

4

一個更優雅的解決方案(和更「正確」)將使用智能 指針:

MyObject func2() 
{ 
    return *std::auto_ptr<MyObject>(func1()); 
} 

(有一個更現代的編譯器,使用std::unique_ptr或者,如果你使用 升壓,你也可以使用boost::scoped_ptr。)

我說的更「正確」,因爲如果MyObject 拷貝構造函數拋出一個異常,這個解決方案仍然會刪除對象,其中 因爲你會泄漏。

+0

Thanx。順便說一句,哪個編譯器對GCC來說是「現代」的? – Morse

+0

@莫爾斯我真的不知道。由於我必須針對大量不同的編譯器,因此我並不真正瞭解編譯器在哪些方面具有更新的功能。無論如何我一般都不能使用它們。我暫時使用'auto_ptr',除非我正在處理非可移植代碼和我使用的編譯器'unique_ptr'。如果你想看看你是否得到了支持,只需加入'',然後嘗試聲明一個。 –

1

是的,這將解決內存泄漏。

這不是一個很好的模式,一般來說。但是,我不確定你想在這裏實現什麼!

+0

Downvoter:關心評論? –

+0

(不是我的downvote)只要複製構造函數不拋出,它就會解決它。 –

0

只要改變func2()這個:

MyObject func2() { return MyObject(); }

動態分配你的情況完全無用。

0

是的,您的第二個解決方案將解決問題,代價是更多副本。

我的問題是:爲什麼你想在堆上分配一個對象(帶有新的)只是爲了將它複製到一個堆棧分配的對象,並在之後立即刪除它。爲什麼不在開始時簡單地在堆棧上創建它?

如下你可以寫:

void main() { 
    MyObject obj; 
} 

你會在最後得到完全相同的結果。它會更簡單!

+0

只要複製構造函數不拋出,它就會解決它。 –

1

,以避免內存泄漏的最佳方法是使用一個智能指針:

#include <memory> 

MyObject func2() { 
    std::unique_ptr<MyObject> obj(func1()); 
    // stuff here 
    return *obj; 
} 

int main() { 
    MyObject obj = func2(); 
} 

這是幾乎相同的解決方案,但解決了你有,如果在複製一個異常被拋出的內存泄漏對象或做「東西」。如果您不使用C++ 11,則使用auto_ptr而不是unique_ptr

0

恕我直言,最好的辦法是刪除func1中的對象,如果它必須刪除NULL。 在func2中,如果我們收到空指針,我們無法以任何方式解引用它。

+0

erm ..再看看你的答案... – Nim

+0

Whooops。固定。 – serenheit

0

如果你不能確定是否會func1返回一個有效的對象與否,而不是返回一個指針,boost::optional可適當 - 這會讓func2檢查是否func1返回的東西有效,而不會使你必須分配動態的東西。