C++ 动态分配是否将数据存储在堆中的随机位置?
我知道局部变量将有序地存储在堆栈上 <>但是,当我在C++中堆内存中动态分配变量时,类似于这个。C++ 动态分配是否将数据存储在堆中的随机位置?,c++,caching,heap,dynamic-memory-allocation,C++,Caching,Heap,Dynamic Memory Allocation,我知道局部变量将有序地存储在堆栈上 但是,当我在C++中堆内存中动态分配变量时,类似于这个。 int * a = new int{1}; int * a2 = new int{2}; int * a3 = new int{3}; int * a4 = new int{4}; 问题1:这些变量是否存储在连续的内存位置? 问题2:如果不是,是因为动态分配将变量存储在堆内存中的随机位置吗? 问题3:那么动态分配是否会增加缓存未命中的可能性并具有较低的空间局部性?第1部分:单独的分配是否连续? 答案是
int * a = new int{1};
int * a2 = new int{2};
int * a3 = new int{3};
int * a4 = new int{4};
问题1:这些变量是否存储在连续的内存位置?
问题2:如果不是,是因为动态分配将变量存储在堆内存中的随机位置吗?
问题3:那么动态分配是否会增加缓存未命中的可能性并具有较低的空间局部性?第1部分:单独的分配是否连续?
答案是可能不是。动态分配如何发生取决于实现。如果像上面的例子那样分配内存,两个单独的分配可能是连续的,但不能保证会发生这种情况(而且永远不应该依赖于它)
<>不同的C++实现使用不同的算法来决定内存分配的方式。p>
第二部分:分配是随机的吗?
有点;但并非完全如此。内存并不是故意以随机方式分配的。通常情况下,内存分配器会尝试分配彼此相邻的内存块,以最小化页面错误和缓存未命中,但这并不总是可能做到
分配分两个阶段进行:
- 尝试减少间接寻址的数量(通过让数组按值而不是按指针存储对象)李>
- 确保您正在操作的内存在设计允许的范围内是连续的(因此使用std::array或std::vector,而不是链表,并且更喜欢一些大的分配,而不是许多小的分配);及
- 尝试设计算法,使其在内存中的跳转次数尽可能少
- 更喜欢使用
而不是MyClass x{}
MyClass*x=newmyclass{}代码>,以及
- 首选
而不是std::vector
李>std::vector
通过扩展,如果您可以使用静态多态性(即模板),请使用该多态性而不是动态多态性 < P> iMHO:这是操作系统特定的/C++标准库实现。
new
最终使用较低级别的虚拟内存分配服务,并使用诸如mmap和munmap之类的系统调用一次分配多个页面。new
的实现可以在相关的时候重用以前释放的内存空间。
新的实施可以对“大”和“小”分配使用各种不同的策略
在您给出的第一个new
结果的示例中,系统调用内存分配(通常是几页),分配的内存可能足够大,以便后续new
调用会导致连续分配。但这取决于实现
我甚至不确定局部变量是否需要存储在堆栈上和/或有序存储。我认为没有这样的保证。局部变量有时存储在堆栈上,有时存储在cpu寄存器中,有时完全优化(编译器可能非常聪明)。当它们存储在堆栈上时,它们可能是按顺序存储的,但是有空间填充以保持内存对齐,并且在表达式的上下文中,临时变量也可能在该表达式的持续时间内占用堆栈上的空间。