顺序“新”运算符是否会产生连续的分配内存?

时间:2016-07-31 03:32:21

标签: c++

我听说std :: vector很好,因为它保证了连续分配的内存(缓存友好)。那么顺序'new'运算符怎么样?

{
    new Test1();
    new Test2();
    new Test3();
}

它不会在堆上创建连续的已分配内存吗?

3 个答案:

答案 0 :(得分:3)

顺序new表达式不一定分配顺序的内存块。

但是C ++ 14对这样的new表达式序列有特殊支持,在某些情况下它们可以用单个new表达式替换(必须分配足够大的连续表达式)内存),以及用单个delete表达式替换相应的delete表达式。

C ++ 14(N3936草案)§5.3.4/ 10:
  

允许实现省略对可替换全局分配函数的调用(18.6.1.1,18.6.1.2)。当它这样做时,存储由实现提供,或者通过扩展另一个new - 表达式的分配来提供。实现可以扩展new - 表达式e1的分配,以便为new - 表达式e2提供存储,如果以下情况属实,则分配未扩展:<登记/>    - 在e1评估之前对e2的评估进行了排序    - 只要e2获得存储空间,就会评估e1    - e1e2都调用相同的可替换全局分配函数,并且
   - 如果由e1e2调用的分配函数抛出,则e1e2的评估中抛出的任何异常都将首先在同一个处理程序中捕获,并且
   - e1e2生成的指针值是评估delete - 表达式的操作数,以及
   - 在评估e2 - 表达式之前对delete的评估进行了排序,其操作数是e1生成的指针值。

答案 1 :(得分:0)

内存管理实际上取决于操作系统 - 在运行时,这相当于连续多次调用C malloc函数,即不保证连续分配(尽管可能)。为了保证对象存储在连续的内存块中,它们应该保存在一个数组中。

我不确定你要使用什么应用程序,但在大多数情况下,缓存友好性的加速远远超过了传递对象的开销。缓存友好性只能加速在大型数据库上运行的程序(例如,长数组的合并),因为CPU不需要快速地将数组洗入和移出缓存 - 但是,对于少量对象,你不要我不得不担心缓存,因为它的影响会很小。如果你单独声明每个向量,而不是作为数组中的块,我猜测它们中没有那么多,所以不需要将它们放入数组中,也不会加速你的程序。

答案 2 :(得分:0)

在大多数实现中,分配器将保留以前的空闲内存,您不会期望总是获得连续的内存。

考虑一下这种情况:Test1是一个大型对象,Test2是小型对象,Test3是中等大小。

当您为Test1分配时,当前内存池不具有足够大的可重用内存,因此它请求扩展堆并从那里进行分配。 然后你为小Test2做了,它只是一个微小的对象,有一个以前免费的可重复使用的内存,所以你从那个池中获得Test2

对于Test3,它与Test2类似,但为了提高性能,分配器会为不同的大小范围保留多个池,因此Test3可能不会追溯到Test2。< / p>

注意:所有这些都不是规范所必需的,它取决于实现,这里建议的只是通常的实现之一(进一步阅读:Buddy内存分配)。