【发布时间】:2011-03-17 14:58:25
【问题描述】:
在 C++ 中,当你像这样在堆上创建一个新变量时:
int* a = new int;
你可以告诉 C++ 使用 delete 来回收内存,如下所示:
delete a;
但是,当您的程序关闭时,它会自动释放使用 new 分配的内存吗?
【问题讨论】:
标签: c++ memory dynamic allocation
在 C++ 中,当你像这样在堆上创建一个新变量时:
int* a = new int;
你可以告诉 C++ 使用 delete 来回收内存,如下所示:
delete a;
但是,当您的程序关闭时,它会自动释放使用 new 分配的内存吗?
【问题讨论】:
标签: c++ memory dynamic allocation
不要让别人告诉你是的。 C++ 没有操作系统的概念,所以说“是的,操作系统会清理它”不再是在谈论 C++,而是在谈论在某些环境中运行的 C++,这可能不是你的。
也就是说,如果您动态分配某些东西但从不释放它,那么您已经泄漏了。只有在您调用 delete/delete[] 后,它才能结束其生命周期。在一些操作系统(以及几乎所有桌面操作系统)上,内存将被回收(因此其他程序可能会使用它。)但是内存不与资源相同!操作系统可以释放它想要的所有内存,如果你有一些套接字连接要关闭,一些文件要完成写入等等,操作系统可能不会这样做。重要的是不要让资源泄漏。我听说过一些嵌入式平台甚至不会回收您尚未释放的内存,从而导致泄漏,直到平台重置。
与其动态分配原始数据(意味着您必须明确删除它),不如将它们包装到自动分配(堆栈分配)的容器中;不这样做被认为是不好的做法,并且会使您的代码非常混乱。
所以不要使用new T[N],使用std::vector<T> v(N);。后者不会让资源泄漏发生。不要使用new T;,使用smart_ptr p(new T);。智能指针将跟踪对象并在知道不再使用时将其删除。这称为Scope-bound Resource Management(SBRM,也称为Resource-Acquisition 是Initialization,或RAII。)
请注意,没有单一的“smart_ptr”。你必须选择哪一个是最好的。当前的标准包括std::auto_ptr,但它相当笨拙。 (它不能在标准容器中使用。)最好的办法是使用 Boost 的智能指针部分,或者如果你的编译器支持它,则使用 TR1。然后你会得到shared_ptr,可以说是最有用的智能指针,但还有很多其他的。
如果每个指向动态分配内存的指针都在一个将要销毁的对象中(即,不是另一个动态分配的对象),并且该对象知道要释放内存,则保证该指针被释放。这个问题甚至不应该是一个问题,因为你不应该处于泄漏的位置。
【讨论】:
不,释放它是您的责任。另外,a 必须是指针,所以它应该是:
int *a = new int;
delete a;
这个excellent answer by Brian R. Bondy 详细说明了为什么最好释放a 分配的内存。
显式调用很重要 删除,因为您可能有一些代码 在你想要的析构函数中 执行。比如可能写一些数据 到日志文件。如果你让操作系统免费 你的记忆,你的代码 析构函数不会被执行。
大多数操作系统都会解除分配 程序结束时的内存。但 释放它是一个好习惯 你自己,就像我在操作系统上面说的 不会调用你的析构函数。
至于一般调用删除,是的 你总是想调用删除,或者 否则你会有内存泄漏 你的程序,这将导致新的 分配失败。
【讨论】:
是的,它是自动回收的,但是如果你打算编写一个大量使用堆的巨大程序,而不是在任何地方调用delete,你肯定会很快用完堆内存,这会使你的程序崩溃.
因此,一旦您不再需要说变量。
【讨论】:
delete,否则会耗尽内存导致问题。
不,当程序退出(“关闭”)时,动态分配的内存保持原样
编辑:
阅读其他答案,我应该更准确。动态分配对象的析构函数不会运行,但内存将被任何体面的操作系统回收。
PS:第一行应该是
int* a = new int;
【讨论】:
当您的进程终止时,操作系统会重新控制该进程正在使用的所有资源,包括内存。但是,这当然不会导致 C++ 的析构函数必须运行,因此它不是不显式释放所述资源的灵丹妙药(当然,对于 int 或其他具有 noop dtors 的类型来说,这不是问题;-)。
【讨论】:
当进程终止时,内存会被操作系统回收。当然这个参数在任何情况下都不应该被程序用来不执行适当的内存管理。
【讨论】: