2010-07-18 168 views
7

在C++中,当你像这样在堆上一个新的变量:通过删除这样释放动态分配的内存

int* a = new int; 

你可以告诉C++回收内存:

delete a; 

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

回答

6

是的,它会自动收回,但如果你打算广泛写一个巨大的程序使用堆,而不是叫delete的任何地方,你一定快速耗尽堆内存,这会使您的程序崩溃。

因此,这是一个必须要与每一个new匹配的delete(或delete []如果使用new [])谨慎地管理你的内存和可用动态分配的数据,只要你不再需要上述变量。

+0

执行很长时间的程序也应该删除,否则它们将耗尽内存并导致问题。 – 2010-07-18 19:14:03

+1

我几乎不会说你必须“仔细管理你的记忆”。只需使用RAII容器即可完成。 – GManNickG 2010-07-18 20:07:09

3

当进程终止时,内存被OS收回。当然,在任何情况下,这个论点都不应该被用来不通过程序进行适当的内存管理。

+2

此外,典型的程序要复杂得多,并且在运行时分配大块内存,只需要很短的时间。如果你没有释放这些内存,你的程序将会使用越来越多的不再需要的内存。 – schnaader 2010-07-18 16:56:22

1

不,您有责任将其释放。此外,a必须是一个指针,所以它应该是:

int *a = new int; 
delete a; 

excellent answer by Brian R. Bondy细节为什么它以释放a分配的内存很好的做法。

显式调用 删除,因为你可能在析构函数中的一些代码 要 执行是非常重要的。就像可能将一些数据 写入日志文件一样。如果您让操作系统免费为您提供内存,那么您的代码将不会被执行。

当程序结束时,大部分操作系统都会释放内存 。但是 这是一个很好的做法,自己释放它 ,就像我上面说的OS 不会调用你的析构函数。

至于调用删除一般情况下,是 你总是想打电话删除或 否则你将不得不在 你的程序内存泄漏,这将导致新的 分配失败。

+0

大多数操作系统都为你做这项工作。 – tur1ng 2010-07-18 16:51:43

+1

@ tur1ng:确实如此,但是一些嵌入式操作系统希望你自己清理一下,不会为你这样做。在你真的是个坏主意之后,依靠操作系统清理。 – George 2010-07-18 16:58:50

0

当您的进程终止时,操作系统会重新控制进程正在使用的所有资源(包括内存)。然而,那当然不会导致C++的析构函数必然运行,所以它不是没有明确释放所述资源的灵丹妙药(尽管这对于int或其他类型的noop dtors当然不是问题; )。

1

没有,当程序退出(“关”)的动态分配的内存留的是

编辑:

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

PS:第一行应阅读

int* a = new int; 
+0

啊,是的,因为它是一个指针。谢谢。 – Zerg 2010-07-18 16:52:54

2

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

也就是说,如果你动态地分配一些东西,但从来没有释放它,你已经泄漏。一旦您拨打delete/delete[]就可以结束其使用期限。在一些操作系统的(和几乎所有的桌面操作系统的),内存将被回收(所以其他程序可能会使用它)。但内存是不是相同的资源!操作系统可以释放所有需要的内存,如果你有一些套接字连接关闭,某些文件完成写入操作等,操作系统可能不会这样做。不要让资源泄漏很重要。我听说过一些嵌入式平台,它们甚至不会回收你没有释放的内存,导致泄漏,直到平台重置。

而不是动态分配的东西原始(意思是你必须明确删除它),将它们包装到自动分配(堆栈分配)的容器;不这样做被认为是不好的做法,并使你的代码非常混乱。

所以不要使用new T[N],请使用std::vector<T> v(N);。后者不会让资源泄漏发生。请勿使用new T;,请使用smart_ptr p(new T);。智能指针将跟踪对象并在知道更长时间使用时将其删除。这称为作用域绑定资源管理(SBRM,也称为资源获取即初始化,或RAII。)

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

如果指向动态分配的内存的每个指针都在一个将会破坏的对象中(即不是另一个被动态分配的对象),并且该对象知道释放内存,则该指针保证被释放。这个问题甚至不应该成为问题,因为你永远不应该泄漏。