8

在 C++ 中使用动态分配的对象时,例如:

TGraph* A = new TGraph(...);

应该始终delete使用这些,否则当控制权交还给父范围时,对象可能仍在内存中。虽然我可以理解为什么程序的子作用域和子例程都是如此,但main作用域也同样重要吗?

我是否必须使用delete内部动态构建的对象main()?这对我来说似乎有点多余的原因是当main结束时,程序也结束了,所以不必担心内存泄漏。

4

7 回答 7

13

大多数现代操作系统总是回收分配给程序(进程)的所有内存。
操作系统并不真正了解您的程序是否泄漏了内存,它只是收回了分配的内容。

但手头的问题不仅仅是记忆丧失:

delete请注意,如果需要调用的对象的析构函数执行一些重要的操作,并且您的程序依赖于它产生的副作用,那么您的程序就会成为未定义行为的牺牲品[参考 1]。一旦发生这种情况,所有赌注都将关闭,您的程序可能会显示任何行为。

此外,操作系统通常会回收分配的内存而不是其他资源,因此您可能会间接泄漏这些资源。这可能包括处理文件描述符或程序本身状态等的操作。

因此,最好总是通过调用deletedelete []在退出程序之前释放所有分配。


[参考 1] C++03 标准 3.8 第 4 段:

"....如果没有显式调用析构函数或者如果没有使用删除表达式 (5.3.5) 来释放存储,则不应隐式调用析构函数并且生成任何依赖于副作用的程序析构函数具有未定义的行为。”

于 2012-04-23T09:23:55.753 回答
7

IMO 最好始终delete正确调用:

  • 让它成为一种自动的习惯,使它在真正需要时不太可能忘记它
  • 涵盖需要释放非内存资源(套接字、文件句柄等)的情况——操作系统不会自动释放这些资源
  • 当有问题的代码可能移出main范围时,以适应未来的重构
于 2012-04-23T09:25:17.937 回答
3

是的,你应该打电话delete,至少因为这是最佳做法。如果你的析构函数中有重要的逻辑,那是你应该调用delete.

更正:如果程序依赖于析构函数中的逻辑,则不delete显式调用会导致未定义的行为。

于 2012-04-23T09:23:01.087 回答
0

这对我来说似乎有点多余的原因是当 main 结束时,程序也结束了,所以不必担心内存泄漏。

你是对的,但考虑一下:你创建了一个类对象,它打开了与远程数据库的连接。在你的程序完成后,你应该告诉数据库“我已经完成了,我要断开连接”,但如果你没有正确调用 delete,它就不会发生。

于 2012-04-23T09:32:57.417 回答
0

取消分配已分配内存的最佳实践。您应该记住,堆内存是有限的,并且在程序运行时仅分配而不取消分配可能会为其他/或同一程序运行堆空间(如果它是某种旨在运行的守护进程)很长一段时间)需要堆。

当然,内存将在程序执行结束时由操作系统回收。

于 2012-04-23T09:35:57.103 回答
0

我看到您正在使用 ROOT(CMS 家伙?)。我认为 ROOT 会处理这个并进行清理,不是吗?

于 2012-04-23T09:50:31.130 回答
0

最佳实践:

  1. 不使用new,使用自动分配
  2. 当需要动态分配时,使用 RAII 确保自动清理

您永远不必编写delete应用程序代码。

在这里,你为什么new打电话TGraph

TGraph A(...);

效果更好:减少烦恼!

于 2012-04-23T11:14:19.177 回答