如何删除已解除引用的对象?

时间:2011-08-19 11:11:43

标签: c++ memory-leaks

我有以下代码

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:添加了一些评论,以便人们不认为我是愚蠢的

7 个答案:

答案 0 :(得分:4)

更优雅的解决方案(更“正确”)将是使用智能 指针:

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

(使用更现代的编译器,使用std::unique_ptr。或者如果您正在使用 提升,你也可以使用boost::scoped_ptr。)

我说更“正确”,因为如果是MyObject的复制构造函数 抛出一个异常,这个解决方案仍然会删除对象,在哪里 因为你会泄漏。

答案 1 :(得分:1)

是的,这将解决内存泄漏。

一般来说,这不是一个非常好的模式。但后来我不确定你在这里想要达到的目标!

答案 2 :(得分: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

答案 3 :(得分:0)

只需将func2()更改为:

MyObject func2() { return MyObject(); }

在您的情况下,动态分配完全没用。

答案 4 :(得分:0)

是的,您的第二个解决方案将以更多副本为代价来解决问题。

我的问题是:为什么要在堆上分配一个对象(使用new)只是为了将它复制到堆栈分配的对象,然后立即将其删除。你为什么不在开始时只在堆栈上创建它?

您可以按如下方式编写:

void main() {
    MyObject obj;
}

最后你会得到完全相同的结果。而且它会简单得多!

答案 5 :(得分:0)

恕我直言,最好的方法是删除func1中的对象,如果它必须删除NULL。 在func2中,如果我们收到空指针,我们就不能以任何方式取消引用它。

答案 6 :(得分:0)

如果您不确定func1是否会返回有效对象,而不是返回指针,boost::optional可能是合适的 - 这会让func2检查{是否{ {1}}返回了一些有效的内容,而不必动态分配任何内容。