C++何时应该在堆上进行分配,何时应该在栈上进行分配?

4

在提出另一个问题之前(或之后),我在想如何判断创建对象时是将其放在堆上还是保留为栈上的对象?为了进行正确的分配,我应该问自己关于这个对象什么样的问题呢?

5个回答

9

如果可以的话,将其放在栈上,否则放在堆上。

哪些东西需要放在堆上?所有长度不确定的对象。任何可能需要为null的对象。任何非常大的对象,以免引起堆栈溢出。


我同意你的说法,除了我不理解“任何可能需要为null的对象”。你所说的“null”是什么意思?肯定不是传统的NULLnullptr - Mark Lakata

6

简单回答。

当它超出范围时,您想让它停留并能够使用它吗?


2
值得注意的是,即使满足其他条件,将巨大的对象放在堆栈上也不是一个好主意。在C ++中超过堆栈限制真的很无趣。 - Voo
@Voo 是的,但这种情况有多常见呢?容器类动态分配它们的内存,因此我认为可以说一个大小为1KB的对象是(a)巨大且(b)罕见的。让我们考虑一个深度为50的调用堆栈,每个函数的堆栈帧中有20个这样巨大的对象,即使如此,您仍然只有1MB的堆栈。 - us2012
@voo - 你可以增加堆栈大小。你也可以编写不需要堆的代码 - 这是许多安全关键行业所要求的。 - Ed Heal
而必须更改特定于操作系统的限制以执行您的代码,这不会让您觉得设计特别糟糕吗?特别是如果限制取决于输入大小,那就更加棘手了。@us2012罕见情况?我真的希望如此,但如果您恰好处于其中之一,这与关于该怎么做的建议有什么关系呢? - Voo
@voo - 如果你可以避免使用堆(即使用栈),那是值得考虑的。可以节省很多麻烦。 - Ed Heal
显示剩余4条评论

3

根据对象的预期生命周期而定。

  • 如果您希望该对象在函数返回后仍然存在,则使用堆(HEAP),否则使用栈(STACK)

如果将对象放置在堆中,则程序员必须在使用完毕后显式地使用free()或delete来释放它,否则程序将会泄漏内存。


当然,除非你从函数中返回该对象。那么,在许多情况下,最好通过值而不是指向它的指针来返回对象。 - us2012
需要考虑静态数据。 - Ed Heal

2

栈内存非常快。这是因为(a)没有系统开销来分配内存——只需在一条指令中移动堆栈指针即可完成分配,(b)堆栈中的内存是“热”的,因此已经在高速缓存中。堆内存较慢,因为(a)需要大量的系统工作来查找并找到一个空闲的内存块,(b)可能不在高速缓存中,需要驱逐一些您可能需要的数据。

栈内存不会出现碎片。堆可能最终会出现如此碎片化,以至于您无法分配任何内容(尽管讽刺的是仍有足够的未使用内存!)

对于长期存储的数据和大型数据(多KB或更多),必须使用堆。

分配更大的栈的危险在于,如果运行多个线程,则可能会对您造成伤害。必须为“最坏情况”使用情况调整堆栈大小。每个线程都需要自己的堆栈。在高核数机器上(可能有200多个线程运行),您可能不想随意增加堆栈大小。另一方面,堆不需要为“最坏情况”使用情况调整大小——它更加高效。


1

使用堆的两个原因:

1- 您希望在当前范围之后保留数据。

2- 您希望预留大量内存。

除此之外,请使用堆栈。

注意:不要在堆栈上保留大量内存,否则会出现“堆栈溢出”错误;)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接