我知道局部变量将按顺序存储在堆栈中。
但是,当我像这样在c ++中的堆内存中动态分配变量时。
int * a = new int{1};
int * a2 = new int{2};
int * a3 = new int{3};
int * a4 = new int{4};
问题1:这些变量是否存储在连续的内存位置?问题2:如果没有,是因为动态分配存储变量在堆内存中的随机位置?问题3:动态分配是否会增加缓存未命中的可能性并且空间局部性较低?
答案可能不是。动态分配如何发生依赖于实现。如果你像上面的例子那样分配内存,那么两个单独的分配可能是连续的,但是不能保证这种情况发生(并且永远不应该依赖它发生)。
c ++的不同实现使用不同的算法来决定如何分配内存。
有些;但并非完全。内存不会以故意随机的方式分配。通常,内存分配器会尝试在彼此附近分配内存块,以便最大限度地减少页面错误和缓存未命中,但并不总是这样做。
分配分两个阶段进行:
第二个阶段是一个实现可以尝试给你的内存提供接近其他最近分配的内容,但它几乎无法控制第一个阶段(操作系统通常只提供任何可用的内存,而不知道你的其他分配程序)。
如果缓存未命中是代码中的瓶颈,
一个好的一般原则是只使用std :: vector对象,除非你有充分的理由使用更高级的东西。因为它们具有更好的缓存局部性,所以std :: vector在插入和删除元素方面比std :: list更快,甚至多达几十甚至几百个元素。
最后:尝试利用堆栈。除非有一个很好的理由让某些东西成为指针,否则只需将其声明为存在于堆栈中的变量。如果可能,
MyClass x{};
而不是MyClass* x = new MyClass{};
,和std::vector<MyClass>
而不是std::vector<MyClass*>
。通过扩展,如果您可以使用静态多态(即模板),请使用它而不是动态多态。
恕我直言这是操作系统特定/ C ++标准库实现。
new
最终使用较低级别的虚拟内存分配服务,并使用mmap和munmap等系统调用一次分配多个页面。 new
的实现可以在相关时重用以前释放的内存空间。 new
的实施可以使用各种不同的策略进行“大”和“小”分配。
在示例中,您给出了第一个new
结果系统调用内存分配(通常是几页),分配的内存可能足够大,以便随后的new
调用导致连续分配。但这取决于实现
简而言之: