【问题标题】:How do I delete an object that was dereferenced?如何删除已取消引用的对象?
【发布时间】:2011-08-19 11:11:43
【问题描述】:

我有以下代码

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:添加了一些 cmets,这样人们就不会认为我非常愚蠢

【问题讨论】:

  • "func1() 在某些情况下返回 NULL",但您在没有测试的情况下取消引用它?
  • 我当然会检查一下。实际上我在那里做了很多事情,我只是不想把它们都放在这里,因为它们无关。
  • 究竟如何 func1 返回NULL?运算符new 抛出,不返回NULL。
  • @More 那么请提供更多信息。为什么要动态分配立即复制到堆栈并丢弃的东西?

标签: c++ memory-leaks


【解决方案1】:

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

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

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

我说的更“正确”,因为如果MyObject的复制构造函数 抛出异常,此解决方案仍将删除对象,其中 因为你的会泄漏。

【讨论】:

  • 谢谢。顺便说一句,哪个编译器在 GCC 方面足够“现代”?
  • @Morse 我真的不知道。由于我必须针对许多不同的编译器,所以我并没有真正了解编译器在哪里具有新功能。反正我一般都用不上。目前我会使用auto_ptr,除非我正在处理不可移植的代码并且我使用的一个编译器支持unique_ptr。如果你想看看你是否得到了支持,只需包含&lt;memory&gt;,并尝试声明一个。
【解决方案2】:

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

总的来说,这不是一个很好的模式。但是我不确定你想在这里实现什么!

【讨论】:

  • (不是我的反对意见)只要复制构造函数不抛出它就会解决它。
【解决方案3】:

避免内存泄漏的最佳方法是使用智能指针:

#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

【讨论】:

    【解决方案4】:

    只需将func2() 更改为:

    MyObject func2() { return MyObject(); }

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

    【讨论】:

      【解决方案5】:

      是的,您的第二个解决方案将解决问题,但代价是制作更多副本。

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

      你可以这样写:

      void main() {
          MyObject obj;
      }
      

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

      【讨论】:

      • 只要复制构造函数不抛出就会解决。
      【解决方案6】:

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

      【讨论】:

        【解决方案7】:

        如果你不确定func1 是否会返回一个有效的对象,而不是返回一个指针,boost::optional 可能是合适的——这会让func2 检查func1 是否返回了有效的东西,而不必动态分配任何东西。

        【讨论】:

          猜你喜欢
          • 2022-06-14
          • 2014-10-16
          • 1970-01-01
          • 2017-06-17
          • 1970-01-01
          • 2023-02-01
          • 2011-01-12
          • 2023-03-31
          • 1970-01-01
          相关资源
          最近更新 更多