2

我只看到了这个缺点:你可以获得 StackOverflow :) 为什么不只使用堆?

在 Java、C、C++ 中,函数的参数在堆栈上传递。函数体内的普通变量是在堆栈中创建的。

据我所知,每个线程的堆栈是有限的,有一些默认值,但相对较低:1-8 Mb。为什么不使用堆而不是堆栈。两者都在内存中,只是操作系统从地址 A 到 B 是堆,从 C 到 D 是堆栈。

有可变参数。它说有 10 个变量,每个变量 4 字节。如果您阅读 11 比您可能会读取一些数据“内存”垃圾,并且可能正是您想要进行黑客攻击的数据,或者您可能会遇到分段错误......如果操作系统检测到您是坏孩子。:) - 所以安全不能成为使用 Stack 的理由。

4

6 回答 6

6

性能是众多原因之一:堆栈中的内存对于簿记来说是微不足道的;它没有孔;可以直接映射到缓存中;它是基于每个线程附加的。

相反,堆中的内存是一堆东西。记账比较困难;它可以有孔。

查看这个答案(我认为非常好)解释了其他一些差异。

于 2013-10-26T17:21:54.280 回答
3

其他人已经提到,由于增加/减少堆栈指针的简单性,堆栈可以更快。然而,这与整个故事相去甚远。

首先,如果您使用的是压缩堆的垃圾收集器(即大多数现代收集器),堆上的分配与堆栈上的分配没有太大区别。您只需在已分配内存和可用内存之间保留一个指向边界的指针,并分配一些空间,您只需移动该指针,就像在堆栈上一样。生命周期极短的对象(如大多数函数中的本地对象)在 GC 周期中也几乎没有成本。保持活动对象可访问需要(一点)工作,但不再可访问的对象通常几乎不需要工作。

然而,对大多数变量使用堆栈通常仍然有很大的优势。许多典型的程序倾向于使用几乎恒定数量的堆栈空间运行相当长的时间。他们进入一个函数,创建一些变量,使用一段时间,将它们从堆栈中弹出,然后在另一个函数中重复相同的循环。

这意味着堆栈顶部的大部分内存几乎总是在缓存中。大多数函数调用都在重用刚刚被前一个函数调用腾出的内存。通过连续重用相同的内存,您最终会获得更好的缓存使用率。

相比之下,当您在堆中分配项目时,您通常最终会为几乎每个项目分配单独的空间。您的缓存处于“流失”的恒定状态,丢弃您不再是用户的对象的内存,以便为新分配的对象腾​​出空间。除非你使用一个很小的堆,否则在缓存中重用地址的机会几乎是不存在的。

于 2013-10-26T17:46:24.817 回答
2

我敢肯定这在网上得到了一百万次的回答,但是......

因为您不希望每个方法调用都是内存分配(慢)。因此,您预先分配了堆栈。

此处列出了更多原因(包括安全性)。

于 2013-10-26T17:19:52.383 回答
1

如果一切都在堆栈上,那么每次传递这些值时,都必须复制它们。然而,与堆不同的是,它不需要巧妙地管理——堆上的项目需要垃圾回收。

所以它们以两种不同的方式工作,适合两种不同的用途。堆栈是一个快速而轻量级的家,用于在短时间内保存值,而堆允许您在不复制对象的情况下传递对象。

堆栈和堆都不适合每种情况——这就是它们都存在的原因。

于 2013-10-26T17:23:08.233 回答
1

答案是在堆上分配和取消分配时会出现漏洞。这意味着分配内存变得越来越困难,因为可用的位置大小不同。堆栈仅保留所需的内容,并在超出范围时将其全部归还。没有麻烦。

于 2013-10-26T17:17:18.920 回答
1

使用堆需要从堆中“请求”一点内存,使用new或一些类似的功能。然后,当它完成时,你delete再次它。这对于长期存在的变量和/或占用大量空间(或占用“编译时未知”空间)的变量非常有用 - 例如,如果您将字符串从文件中读取到变量中,您不一定知道它需要多少空间,而且从程序中收到一条消息说“文件 Y 中 X 行的字符串太大”真的很烦人)。

另一方面,堆栈在分配和取消分配时都是“空闲的”(从技术上讲,任何使用堆栈空间的函数都需要一条额外的指令来分配堆栈空间,但与数百或调用new将涉及数千个,这并不明显)。当然,class对象仍然必须调用它们各自的构造函数,这可能需要几乎任何时间才能完成,但无论从何处/如何分配存储都是如此。

于 2013-10-26T17:28:11.463 回答