Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;是否需要删除主作用域末尾的动态分配对象? 在C++中使用动态分配的对象EG: TGraph* A = new TGraph(...);_C++_Memory Management_Memory Leaks - Fatal编程技术网

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)如果不用于释放存储,则不应隐式调用析构函数,任何依赖于析构函数产生的副作用的程序都有未定义的行为。“假设“您不需要…”是错误的。如果析构函数不是构造函数。@是的,这就是我说的…:DUse
    std::unique_ptr A(新的TGraph(…)
    ),问题就消失了。@larsmans:这需要访问C++11。如果要在指针超出范围时删除对象,为什么要首先使用动态分配。“应该总是删除这些”的说法一开始就错了。@nicolas:true。在C++03中,
    auto_ptr
    的作用大致相同。实际上,我在学校需要它。除了对高能物理很好的支持外,它还是一个非常好的数据分析包。如果root用户自己清除了,就没有线索了。@罗密欧:如果你确信析构函数被调用,一个设计良好的(样式)C++对象会自动清除。@拉斯曼:所以没有<代码>删除>代码>,不调用析构函数,也没有清理。所以如果我不需要调用析构函数,我就忽略了良好的实践。我可以把它留在这里,不删除。@romeovs:是的。内存将被所有现代操作系统回收。@romeovs:请注意,仅仅因为你能做某事并不意味着你应该做。不删除东西仍然是不好的形式。尽管有人想知道,如果它不能在t结束后存活下来,为什么还要堆分配它呢