7

在 C++ 中,当您像这样在堆上创建一个新变量时:

int* a = new int;

你可以告诉 C++ 使用 delete 来回收内存,如下所示:

delete a;

但是,当您的程序关闭时,它会自动释放新分配的内存吗?

4

6 回答 6

6

是的,它是自动回收的,但是如果你打算编写一个大量使用堆而不delete在任何地方调用的巨大程序,你肯定会很快耗尽堆内存,这会使你的程序崩溃。

因此,一旦您不再需要所述变量,就必须仔细管理您的内存并释放动态分配的数据,并与delete每个new(或delete []如果使用)匹配。new []

于 2010-07-18T16:52:20.597 回答
3

当进程终止时,内存由操作系统回收。当然,这个参数在任何情况下都不应该被程序用来不执行正确的内存管理。

于 2010-07-18T16:50:29.437 回答
2

不要让人们告诉你是的。C++ 没有操作系统的概念,所以说“是的,操作系统会清理它”不再是在谈论 C++,而是在谈论在某些环境中运行的 C++,这可能不是你的。

也就是说,如果您动态分配某些东西但从不释放它,那么您已经泄漏了。delete一旦你调用/它,它只能结束它的生命周期delete[]。在某些操作系统(以及几乎所有桌面操作系统)上,内存将被回收(因此其他程序可能会使用它。)但是内存资源不同!操作系统可以释放它想要的所有内存,如果你有一些套接字连接要关闭,一些文件要完成写入等等,操作系统可能不会这样做。重要的是不要让资源泄漏。我听说过一些嵌入式平台甚至不会回收您尚未释放的内存,从而导致泄漏,直到平台重置。

与其动态分配原始内容(意味着您是必须明确删除它的人),不如将它们包装到自动分配(堆栈分配)的容器中;不这样做被认为是不好的做法,并使您的代码非常混乱。

所以不要用new T[N],用std::vector<T> v(N);。后者不会让资源泄漏发生。不使用new T;,使用smart_ptr p(new T);。智能指针将跟踪对象并在知道不再使用时将其删除。这称为 Scope-bound 资源管理(SBRM,也被称为哑名称 Resource-Acquisition 是 Initialization,或 RAII。)

注意没有单一的“ smart_ptr”。你必须选择哪一个是最好的。当前的标准包括std::auto_ptr,但它非常笨拙。(它不能在标准容器中使用。)最好的办法是使用 Boost 的智能指针部分,或者如果你的编译器支持它,则使用 TR1。然后你会得到shared_ptr,可以说是最有用的智能指针,但还有很多其他的。

如果每个指向动态分配内存的指针都在一个将要销毁的对象中(即,不是另一个动态分配的对象),并且该对象知道要释放内存,则保证该指针被释放。这个问题甚至不应该是一个问题,因为你不应该处于泄漏的位置。

于 2010-07-18T17:51:59.563 回答
1

不,释放它是你的责任。此外,a必须是一个指针,所以它应该是:

int *a = new int;
delete a;

Brian R. Bondy的这个出色回答详细说明了为什么释放a.

显式调用 delete 很重要,因为您可能在析构函数中有一些要执行的代码。就像可能将一些数据写入日志文件一样。如果您让操作系统为您释放内存,您的析构函数中的代码将不会被执行。

大多数操作系统会在程序结束时释放内存。但是最好自己释放它,就像我在上面所说的那样,操作系统不会调用你的析构函数。

至于一般调用 delete,是的,您总是想调用 delete,否则您的程序中会出现内存泄漏,这将导致新的分配失败。

于 2010-07-18T16:50:50.387 回答
1

不,当程序退出(“关闭”)时,动态分配的内存保持原样

编辑:

阅读其他答案,我应该更准确。动态分配对象的析构函数不会运行,但内存将被任何体面的操作系统回收。

PS:第一行应该是

int* a = new int;
于 2010-07-18T16:51:45.923 回答
0

当您的进程终止时,操作系统会重新控制该进程正在使用的所有资源,包括内存。但是,这当然不会导致 C++ 的析构函数必须运行,因此它不是不显式释放所述资源的灵丹妙药(当然,对于int具有 noop dtor 的其他类型来说,这不会是问题;-) .

于 2010-07-18T16:51:14.997 回答