52

例如,在我的 C++main函数中,如果我有一个指向使用堆内存(而不是堆栈内存)的变量的指针 - 这会在我的应用程序退出后自动释放吗?我会这样认为。

即便如此,即使您认为在退出时自动释放内存的情况下永远不会使用它们,也总是删除堆分配是一种好习惯吗?

例如,这样做有什么意义吗?

int main(...)
{
    A* a = new A();
    a->DoSomething();
    delete a;
    return 0;
}

我在想如果我重构(或其他人重构)该代码并将其放在应用程序中的其他位置,delete那么真的有必要。

除了 Brian R. Bondy 的回答(专门讨论了 C++ 中的含义)之外,Paul Tomblin对一个 C 特定问题也有很好的回答,该问题也谈到了 C++ 析构函数。

4

8 回答 8

79

显式调用 delete 很重要,因为您可能在析构函数中有一些要执行的代码。就像可能将一些数据写入日志文件一样。如果您让操作系统为您释放内存,您的析构函数中的代码将不会被执行。

大多数操作系统会在程序结束时释放内存。但是最好自己释放它,就像我在上面所说的那样,操作系统不会调用你的析构函数。

至于一般调用 delete,是的,您总是想调用 delete,否则您的程序中会出现内存泄漏,这将导致新的分配失败。

于 2009-03-24T15:07:22.073 回答
29

是的,当您通过内存泄漏检测工具运行程序时,它有助于消除误报。

于 2009-03-24T15:28:32.817 回答
13

是的。

  • 该标准不保证操作系统会清理内存。您可以在主流平台上期待这一点,但为什么要冒险呢?
  • 如果您不故意泄漏内存,则可以最大限度地减少 valgrind 等工具报告的混乱情况。
  • 如果你养成了这个习惯,谁能说你有一天会不小心将这种方法应用到重要的地方呢?
  • 可能需要对象销毁。通常只是假设你这样做。它不会伤害你。
于 2011-05-14T17:00:02.027 回答
8

想想你的班级A不得不破坏。
如果您不调用deleteon a,则不会调用该析构函数。通常,如果过程结束,这并不重要。但是如果析构函数必须释放例如数据库中的对象呢?将缓存刷新到日志文件?将内存缓存写回磁盘?

你看,删除对象不仅仅是“好习惯”,在某些情况下它是必需的。

于 2009-03-24T15:18:47.833 回答
7

考虑要删除的对象获取操作系统无法安全释放的外部资源的情况。如果你不对那个对象调用 delete,那么你就有了真正的泄漏。

于 2009-03-24T15:19:50.793 回答
4

显式删除对象的另一个原因是,如果您的应用程序存在真正的内存泄漏,那么使用valgrind之类的工具来查找泄漏会变得更容易,前提是您不必筛选因不清理而产生的“泄漏”。

于 2009-03-24T15:28:57.170 回答
4

删除的另一个原因是避免您将来可能使用的检漏仪发出错误警报。如果您有误报,您可能不会注意到检漏仪报告的真实泄漏 - 它将被掩埋在报告中的虚假泄漏中。

于 2009-03-24T15:29:23.377 回答
3

始终确保您自己删除它。操作系统会处理这个问题,但会排除可以轻松避免的错误

于 2009-03-24T15:26:31.417 回答