C++;是否需要删除主作用域末尾的动态分配对象? 在C++中使用动态分配的对象EG: TGraph* A = new TGraph(...);
人们应该总是C++;是否需要删除主作用域末尾的动态分配对象? 在C++中使用动态分配的对象EG: TGraph* A = new TGraph(...);,c++,memory-management,memory-leaks,C++,Memory Management,Memory Leaks,人们应该总是删除这些对象,否则,当 控件返回到父作用域。虽然我可以理解为什么程序的子作用域和子例程也是如此,但是main作用域是否也一样 我是否必须删除在main()中动态构建的对象?对我来说,这似乎有点多余的原因是当main结束时,程序也会结束,因此不必担心内存泄漏。是的,您应该调用delete,至少因为这是最佳实践。如果析构函数中有重要的逻辑,那么这就是您应该调用delete的另一个原因 更正:如果程序依赖于析构函数中的逻辑,不显式调用delete将导致未定义的行为 大多数现代操作系统总是回
删除这些对象,否则,当
控件返回到父作用域。虽然我可以理解为什么程序的子作用域和子例程也是如此,但是main
作用域是否也一样
我是否必须删除在main()
中动态构建的对象?对我来说,这似乎有点多余的原因是当main
结束时,程序也会结束,因此不必担心内存泄漏。是的,您应该调用delete
,至少因为这是最佳实践。如果析构函数中有重要的逻辑,那么这就是您应该调用delete
的另一个原因
更正:如果程序依赖于析构函数中的逻辑,不显式调用delete
将导致未定义的行为 大多数现代操作系统总是回收分配给程序(进程)的所有内存。
操作系统并不真正理解如果你的程序泄漏了内存,它只会收回分配的内存
但手头还有比记忆丧失更大的问题:
请注意,如果需要调用delete
的对象的析构函数执行一些非平凡的操作,并且您的程序依赖于它产生的副作用,那么您的程序将成为未定义行为的牺牲品。一旦发生这种情况,所有的赌注都被取消,您的程序可能会显示任何beahvior
此外,操作系统通常会回收分配的内存,但不会回收其他资源,因此您可能会间接泄漏这些资源。这可能包括处理文件描述符或程序本身状态等的操作
因此,在退出程序之前,通过调用delete
或delete[]
来取消分配所有分配是一种很好的做法
[参考文献1]C++03标准3.8第4段:
“…如果没有显式调用析构函数,或者如果没有使用删除表达式(5.3.5)释放存储,则不应隐式调用析构函数,并且依赖于析构函数产生的副作用的任何程序都有未定义的行为。”
在我看来,最好总是正确地调用delete
:
- 让它成为一种自动的习惯,让它在真正需要的时候不太可能忘记它
- 为了涵盖需要释放非内存资源(套接字、文件句柄等)的情况,操作系统不会自动释放这些资源
- 为了满足将来重构的需要,可能会将相关代码移出
main
范围
这对我来说似乎有点多余的原因是当主要部分结束时,
程序也将结束,因此无需担心内存问题
泄露
你是对的,但是考虑一下:你创建了一个类对象,它打开了一个到远程数据库的连接。程序完成后,您应该告诉DB“我完成了,我要断开连接”,但如果您不能正确调用delete,则不会发生这种情况。
这是取消分配已分配内存的最佳做法。您应该记住,堆内存是有限的,当您的程序运行时,只分配而不取消分配可能会为需要堆的其他/或同一程序(如果它是某种守护进程,打算运行很长时间)运行堆空间
当然,在程序执行结束时,操作系统将回收内存。我看到您正在使用ROOT(CMS-guy?)。我认为ROOT会解决这个问题并进行清理,不是吗?最佳实践:
不要使用新的
,使用自动分配
当需要动态分配时,使用RAII确保自动清理
您不必在应用程序代码中写入删除
在这里,您为什么要为TGraph
调用new
TGraph A(...);
效果更好:少担心 我想这是由《答案》的另一位作者完成的。这样一来,他们的答案就更有可能排在列表的最前面(我以前也见过这种情况)。-1因为C++03 3.8说“…如果没有显式调用析构函数,或者如果有删除表达式(5.3.5)如果不用于释放存储,则不应隐式调用析构函数,任何依赖于析构函数产生的副作用的程序都有未定义的行为。“假设“您不需要…”是错误的。如果析构函数不是构造函数。@是的,这就是我说的…:DUsestd::unique_ptr A(新的TGraph(…)
),问题就消失了。@larsmans:这需要访问C++11。如果要在指针超出范围时删除对象,为什么要首先使用动态分配。“应该总是删除这些”的说法一开始就错了。@nicolas:true。在C++03中,auto_ptr
的作用大致相同。实际上,我在学校需要它。除了对高能物理很好的支持外,它还是一个非常好的数据分析包。如果root用户自己清除了,就没有线索了。@罗密欧:如果你确信析构函数被调用,一个设计良好的(样式)C++对象会自动清除。@拉斯曼:所以没有<代码>删除>代码>,不调用析构函数,也没有清理。所以如果我不需要调用析构函数,我就忽略了良好的实践。我可以把它留在这里,不删除。@romeovs:是的。内存将被所有现代操作系统回收。@romeovs:请注意,仅仅因为你能做某事并不意味着你应该做。不删除东西仍然是不好的形式。尽管有人想知道,如果它不能在t结束后存活下来,为什么还要堆分配它呢