C ++中的内存分配区域(堆栈vs堆vs静态)

我知道在C ++中有三个,而不是两个内存区域:堆栈,堆和静态指定function的区域。 我有两个问题

  1. 为什么堆比堆栈慢得多? 当然,它应该只是一个额外的间接水平?

  2. 分配给静态“特性”(variables,函数,类)的内存区域提供的性能比堆更快吗?

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

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

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

就业绩而言,最好不要过于担心业绩。 虽然静态内存很快,但有很多和很多缺点。 你想要做的最后一件事是让你的所有数据都是静态的。

1)为什么堆比堆栈慢得多? 当然,它应该只是一个额外的间接水平?

因为在堆栈上分配内存意味着将堆栈指针增加1 N ,其中N是字节数。 以这种方式改变sp是足够快的。 堆,你做很多事情,找到空闲插槽或请求操作系统内存,例如,昂贵的操作。

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

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

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

比较堆栈,堆或静态分配区域的速度时,有两种不同的速度可供比较。

首先是访问速度 。 虽然本地(堆栈分配)变量可以有一个轻微的优势,因为它们更容易编译器缓存在CPU寄存器中。 否则,它本质上只是内存访问。

其次,有分配速度 。 这是出现巨大差异的地方。
静态分配的对象在程序启动时(或者当它们驻留在一个动态加载的库中的时候是库加载时)保留它们的内存,所以它们的分配时间就程序而言是非常短的。
堆栈分配的对象分配起来也很便宜,因为它们采用可预测的分配模式(最后分配==第一次释放),编译器可以轻松考虑。 例如,如果一个应用程序有多个线程,它也会有多个堆栈(每个堆栈为一个线程保留),所以线程不必为了访问堆栈内存而相互竞争。
堆分配的对象是困难的,因为堆用于不适合在早期的组中很好的一切。 另外,整个应用程序通常只有一个堆,因此需要线程同步来从堆中分配内存。 而且,由于分配/释放模式是相当随机的,因此必须采取措施确保不会由于堆碎片而造成太多的堆内存“丢失”。 这一切都需要一些时间,在分配或取消分配时得到支付。

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

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

static存储而言,它仅适用于数据成员:静态函数和静态成员函数只是简单地重用关键字而不用重新使用它的含义。 静态存储中的对象只被分配一次,所以没有分片的原因。

一旦分配完成,访问三种存储(静态,动态和自动)中的对象的速度将以几乎相同的速度进行。

1)这不是一个间接的问题,这是一个记忆的问题。 在堆栈上分配内存就是将堆栈指针向上移动。 虽然在堆上的分配涉及寻找一个内存segemnt正确的大小,并考虑到碎片。

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

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