9

我知道 C++ 中有三个而不是两个内存区域:堆栈、堆和静态分配功能的区域。我有两个问题

  1. 为什么堆比栈慢这么多?当然它应该只是一个额外的间接级别?

  2. 为静态“特性”(变量、函数、类)分配的内存区域是否提供比堆更快的性能?

4

6 回答 6

14

先说几个旁注。正确的术语是自动而不是堆栈,动态而不是堆。另一个是 C++11 现在有四种而不是三种类型的内存。C++11 添加了线程本地内存。

自动内存速度很快,因为它是在大多数机器上使用调用堆栈实现的。只需将堆栈指针调整适当的数量,瞧!内存已分配。动态内存需要在底层做更多的工作。必要的内存可能没有附加到进程中,要实现这一点需要通过操作系统。即使内存可用,动态内存管理工具仍然必须找到它并将其标记为正在使用。

静态内存作为编译和链接过程的一部分被“分配”。当您在某个源文件中定义静态变量时,编译后的代码包含特殊指令,供链接器为该变量保留空间。编译器还将您的 C/C++ 代码转换为机器代码。链接器将所有这些不同的数据和代码块结合起来,并解析地址以形成可执行的二进制映像。当您运行程序时,该二进制图像被加载到(虚拟)内存中。一旦程序开始执行,该静态变量的内存就存在。

就性能而言,最好不要提前过多担心性能。虽然静态内存很快,但也有很多缺点。您要做的最后一件事是使所有数据静态化。

于 2013-01-05T14:13:00.670 回答
3

When comparing the speed of stack, heap or static allocation areas, there are two different speeds to compare.

First, there is the speed of access. This is comparable for each of the three areas, although local (stack allocated) variables can have a slight edge because they are easier for the compiler to cache in a CPU register. Otherwise, it is essentially just memory access.

Secondly, there is the speed of allocation. This is where the big differences arise.
Statically allocated objects get their memory reserved at program startup (or library load time when they reside in a dynamically loaded library), so their allocation time is immesurably short as far as the program is concerned.
Stack allocated objects are also cheap to allocate, because they take a predictable allocation pattern (last allocated == first deallocated) that the compiler can easily take into account. For example, if an application has multiple threads, it will also have multiple stacks (each stack reserved for one thread), so the threads don't have to compete with each other for access to the stack memory.
Heap allocated objects are the difficult ones, because the heap is used for everything that does not nicely fit within the earlier groups. Also, there is typically only one heap for the entire application, so thread synchronisation is needed to allocate memory from the heap. And, because the allocation/deallocation patterns are fairly random, measures have to be taken to ensure not too much heap memory gets 'lost' due to fragmentation of the heap. This all takes some time that gets paid when doing an allocation or deallocation.

于 2013-01-05T14:21:46.407 回答
3

1)为什么堆比栈慢这么多?当然它应该只是一个额外的间接级别?

因为在堆栈上分配内存意味着将堆栈指针 sp 增加1其中字节数。以这种方式更改sp已经足够快了。使用堆,您可以做很多事情,例如寻找空闲插槽或请求操作系统的内存,这些都是昂贵的操作。NN

1. 或减少,取决于堆栈增长的方式!

2) 为静态“特性”(变量、函数、类)分配的内存区域是否提供比堆更快的性能?

如果您的意思是static变量,那么是的,它们比堆快,因为它们是静态分配的,并且它们一直存在到程序结束。但是,没有类之static类的东西,并且在这种情况下无法比较为函数分配的内存(这个问题对我来说并不完全有意义)。

于 2013-01-05T14:09:45.543 回答
2

尽管“堆更慢”的说法过于宽泛而没有意义,但与堆分配相关的某些方面肯定比堆慢。与堆栈不同,堆栈不能碎片化,因为您无法从堆栈中间移除东西,堆会受到碎片化的影响。您的程序可以按任意顺序取消分配对象,从而在堆中创建“洞”。当您请求更多内存时,分配器必须搜索合适的“洞”来满足您的请求。

此外,基于堆栈的操作由计算机硬件高度优化。最后,在自动存储(“堆栈”的正式名称)中分配的对象由于靠近程序访问的其他本地对象而被缓存的可能性更高。

static存储而言,它仅适用于数据成员:静态函数和静态成员函数只是重用关键字而不重用其含义。静态存储中的对象只分配一次,因此不会产生碎片。

分配完成后,对三种存储(静态、动态和自动)中对象的访问速度几乎相同。

于 2013-01-05T14:11:49.593 回答
1

1)这不是间接问题,而是内存管理问题。在堆栈上分配内存只是将堆栈指针向上移动。虽然堆上的分配涉及寻找合适大小的内存段,并考虑到碎片。

2) 静态内存在程序的主入口点之前分配,因此没有真正的运行时开销。访问已分配内存的速度实际上并不取决于分配内存的位置。

于 2013-01-05T14:11:20.697 回答
-1

堆栈比堆快得多的一个原因是由于局部性原则。存储在堆栈中的数据位于连续的位置,这意味着如果引用一个变量,它的相邻信息会自动被带到缓存中。存储在堆上的数据(动态数组除外)没有这个优势。

于 2013-01-05T14:08:17.450 回答