在 C++ 中使用动态分配的对象时,例如:
TGraph* A = new TGraph(...);
应该始终delete
使用这些,否则当控制权交还给父范围时,对象可能仍在内存中。虽然我可以理解为什么程序的子作用域和子例程都是如此,但main
作用域也同样重要吗?
我是否必须使用delete
内部动态构建的对象main()
?这对我来说似乎有点多余的原因是当main
结束时,程序也结束了,所以不必担心内存泄漏。
在 C++ 中使用动态分配的对象时,例如:
TGraph* A = new TGraph(...);
应该始终delete
使用这些,否则当控制权交还给父范围时,对象可能仍在内存中。虽然我可以理解为什么程序的子作用域和子例程都是如此,但main
作用域也同样重要吗?
我是否必须使用delete
内部动态构建的对象main()
?这对我来说似乎有点多余的原因是当main
结束时,程序也结束了,所以不必担心内存泄漏。
大多数现代操作系统总是回收分配给程序(进程)的所有内存。
操作系统并不真正了解您的程序是否泄漏了内存,它只是收回了分配的内容。
但手头的问题不仅仅是记忆丧失:
delete
请注意,如果需要调用的对象的析构函数执行一些重要的操作,并且您的程序依赖于它产生的副作用,那么您的程序就会成为未定义行为的牺牲品[参考 1]。一旦发生这种情况,所有赌注都将关闭,您的程序可能会显示任何行为。
此外,操作系统通常会回收分配的内存而不是其他资源,因此您可能会间接泄漏这些资源。这可能包括处理文件描述符或程序本身状态等的操作。
因此,最好总是通过调用delete
或delete []
在退出程序之前释放所有分配。
[参考 1] C++03 标准 3.8 第 4 段:
"....如果没有显式调用析构函数或者如果没有使用删除表达式 (5.3.5) 来释放存储,则不应隐式调用析构函数并且生成任何依赖于副作用的程序析构函数具有未定义的行为。”
IMO 最好始终delete
正确调用:
main
范围时,以适应未来的重构是的,你应该打电话delete
,至少因为这是最佳做法。如果你的析构函数中有重要的逻辑,那是你应该调用delete
.
更正:如果程序依赖于析构函数中的逻辑,则不delete
显式调用会导致未定义的行为。
这对我来说似乎有点多余的原因是当 main 结束时,程序也结束了,所以不必担心内存泄漏。
你是对的,但考虑一下:你创建了一个类对象,它打开了与远程数据库的连接。在你的程序完成后,你应该告诉数据库“我已经完成了,我要断开连接”,但如果你没有正确调用 delete,它就不会发生。
取消分配已分配内存的最佳实践。您应该记住,堆内存是有限的,并且在程序运行时仅分配而不取消分配可能会为其他/或同一程序运行堆空间(如果它是某种旨在运行的守护进程)很长一段时间)需要堆。
当然,内存将在程序执行结束时由操作系统回收。
我看到您正在使用 ROOT(CMS 家伙?)。我认为 ROOT 会处理这个并进行清理,不是吗?
最佳实践:
new
,使用自动分配您永远不必编写delete
应用程序代码。
在这里,你为什么new
打电话TGraph
?
TGraph A(...);
效果更好:减少烦恼!