一个对象列表应该存储在堆上还是栈上?

3
我有一个对象(A),其中包含由对象(B)组成的列表。列表中的对象(B)是指针,但是列表本身应该是指针吗?我正在从Java迁移到C ++,还没有完全习惯堆栈/堆。列表不会传递到类A之外,只有列表中的元素。为了保险起见,将列表本身分配在堆上是否是良好的做法?
此外,包含列表(A)的类本身也应该在堆上吗?就像列表一样,它也不会被传递。
5个回答

6
请注意:
  1. 只有当Object-A也在堆栈上时,列表才会在堆栈上。
  2. 即使列表本身不在堆上,它也可能从堆上分配其存储空间。这就是std::list、std::vector和大多数C++列表的工作方式——原因是基于堆栈的元素无法增长。
  3. 现在大多数堆栈大小为1mb左右,因此您需要一个相当大的对象列表才需要担心它。即使您的堆栈只有32kb,您也可以存储接近八千个指针,直到出现问题。
我认为,对于刚开始使用C/C++显式内存管理的人来说,他们往往会过度思考这些问题。
除非你知道自己将使用成千上万个大型对象,否则只需将列表放在堆栈上。除非您在函数中使用巨大的C风格数组,否则由于上述#1和#2,列表使用的内存最终都将在堆上结束。

原因是基于堆栈的元素无法增长。我相信你可以增长一个基于堆栈的元素,但你必须重新分配它们。 - Meric Ozcan

1

如果列表可以增长,那么最好将其存储在堆上。因为您永远不知道运行时堆栈会是什么样子,溢出是一个真正的危险,后果是致命的。

如果您绝对知道列表的上限,并且与您的堆栈大小相比很小,那么您可能可以使用堆栈分配列表。


1
如果列表存储的是指向堆的指针,那么要导致堆栈溢出需要大量元素吗?对于这个应用程序来说,列表拥有超过30个元素已经很疯狂了。 - Alexander
如果是像“std::list”这样的列表,那么它不会在堆上存储任何内容。Bor或任何其他STL容器也是如此。 - Jimmy J

0

我在工作环境中经常需要处理堆栈大小较小且需要避免堆碎片的情况,因此我会使用以下规则:

  • 如果列表很小且大小已知,则使用堆栈。

  • 如果列表很小但大小未知,则可以考虑使用堆和alloca()。如果您能够保证在分配期间函数不会在堆上分配任何内容,则使用堆是一个不错的选择。如果无法保证这一点,则可能会导致碎片,此时使用alloca()将是更好的选择。

  • 如果列表很大或需要增长,则使用堆。如果无法保证它不会产生碎片,我们通常会在内存管理器中构建一些资源来解决这个问题,例如自顶向下的分配和单独的堆。

大多数情况下,人们不需要担心碎片问题,因此他们可能不建议使用alloca。

关于包含列表的类,如果它仅在函数范围内使用,且内部数据结构不是非常大,我会将其放在堆栈上。


0

“list”是什么意思?如果它是std::list(或std::vector或任何其他STL容器),那么它不会在堆栈上存储任何东西,所以不用担心。

如果你有任何疑问,请查看sizeof(A),这将告诉你它在堆栈上使用多少内存。

但是...决策主要应基于对象的生命周期。基于堆栈的对象在超出范围时立即被销毁。


-1

栈始终是最简单的。不幸的是,它有一个很大的缺点 - 你必须提前知道元素的数量。


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