2011-08-19 24 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返回的东西有效,而不会使你必须分配动态的东西。