我听说std :: vector很好,因为它保证了连续分配的内存(缓存友好)。那么顺序'new'运算符怎么样?
{
new Test1();
new Test2();
new Test3();
}
它不会在堆上创建连续的已分配内存吗?
答案 0 :(得分:3)
顺序new
表达式不一定分配顺序的内存块。
但是C ++ 14对这样的new
表达式序列有特殊支持,在某些情况下它们可以用单个new
表达式替换(必须分配足够大的连续表达式)内存),以及用单个delete
表达式替换相应的delete
表达式。
“允许实现省略对可替换全局分配函数的调用(18.6.1.1,18.6.1.2)。当它这样做时,存储由实现提供,或者通过扩展另一个
new
- 表达式的分配来提供。实现可以扩展new
- 表达式e1
的分配,以便为new
- 表达式e2
提供存储,如果以下情况属实,则分配未扩展:<登记/> - 在e1
评估之前对e2
的评估进行了排序 - 只要e2
获得存储空间,就会评估e1
-e1
和e2
都调用相同的可替换全局分配函数,并且
- 如果由e1
和e2
调用的分配函数抛出,则e1
或e2
的评估中抛出的任何异常都将首先在同一个处理程序中捕获,并且
-e1
和e2
生成的指针值是评估delete
- 表达式的操作数,以及
- 在评估e2
- 表达式之前对delete
的评估进行了排序,其操作数是e1
生成的指针值。
答案 1 :(得分:0)
内存管理实际上取决于操作系统 - 在运行时,这相当于连续多次调用C malloc
函数,即不保证连续分配(尽管可能)。为了保证对象存储在连续的内存块中,它们应该保存在一个数组中。
我不确定你要使用什么应用程序,但在大多数情况下,缓存友好性的加速远远超过了传递对象的开销。缓存友好性只能加速在大型数据库上运行的程序(例如,长数组的合并),因为CPU不需要快速地将数组洗入和移出缓存 - 但是,对于少量对象,你不要我不得不担心缓存,因为它的影响会很小。如果你单独声明每个向量,而不是作为数组中的块,我猜测它们中没有那么多,所以不需要将它们放入数组中,也不会加速你的程序。
答案 2 :(得分:0)
在大多数实现中,分配器将保留以前的空闲内存,您不会期望总是获得连续的内存。
考虑一下这种情况:Test1
是一个大型对象,Test2
是小型对象,Test3
是中等大小。
当您为Test1
分配时,当前内存池不具有足够大的可重用内存,因此它请求扩展堆并从那里进行分配。
然后你为小Test2
做了,它只是一个微小的对象,有一个以前免费的可重复使用的内存,所以你从那个池中获得Test2
。
对于Test3
,它与Test2
类似,但为了提高性能,分配器会为不同的大小范围保留多个池,因此Test3
可能不会追溯到Test2
。< / p>
注意:所有这些都不是规范所必需的,它取决于实现,这里建议的只是通常的实现之一(进一步阅读:Buddy内存分配)。