我听到了关于此事的相互矛盾的意见。
有人说访问分配在堆上的数据(即std::vector或通过分配的动态数组malloc)总是比访问分配在堆栈上的数据稍慢,因为进程必须始终通过中间指针来访问该数据,该数据可能位于完全不同的内存区域;另一方面,他们认为,访问堆栈上分配的数据不需要通过这个中间指针,并且该数据可能已经被缓存。
其他人声称,只有数据在堆上的分配比在堆栈上慢(因为malloc、mmap和类似函数的开销),但访问则不然,除了堆栈和堆位于不同物理驱动器上的极少数情况外。
真相是什么?
事实上(至少在大多数现代 CPU 上),堆栈和堆的性能相同,因为它们都只是 RAM 的一部分。所以取消引用指针几乎是一样的。
不同之处在于堆栈是为您的进程/线程预先分配的,因此您不需要系统malloc调用free来使用它。尤其malloc是成本高昂。另一个区别是,可能有一些特定的 CPU 指令用于处理堆栈以提高性能(例如,程序集的push、pop)。然而,这些本身不太可能与内存访问(如将内存加载到寄存器)有任何关系。
另一个区别是,如果你用完堆栈,你的程序将(更有可能)崩溃。然而,如果您用完了堆,那么您的操作系统可能会为您使用交换,从而使性能降低数千倍。
缓存未命中当然是一个因素,并且它更常发生在堆上而不是堆栈上。但这只是因为堆与堆栈相比非常大。但请注意,除非您正在编写占用大量 CPU 的代码,否则缓存未命中实际上并不那么重要。
现在你是对的,std::vector必须取消引用额外的时间。但这里缓慢的是取消引用,而不是那些位于堆栈或堆上的指针。他们在哪里并不重要。双重解除引用总是比单一解除引用慢。
现在堆栈和堆也可能位于不同的物理设备上。并且这两个设备具有不同的速度(可能堆速度更快)。但这又与堆栈和堆本身无关。这可能发生在内存的任何两个部分。而你对此无能为力。甚至操作系统也不能(好吧,也许可以,我对此不确定)。是主板的事。而且主板很可能会对更快的设备进行降频。