比std :: vector更快地收集对象

时间:2018-03-23 16:01:45

标签: c++

我有一个函数可以在向量中存储很多小对象(~16个字节),但事先并不知道将存储多少个对象(例如,想象一个存储标记的递归下降解析器)

std::vector<SmallObject> getObjects();

由于所有的重新分配和复制,这很慢(显然C ++甚至必须调用复制构造函数if you don't use an optimised version(参见&#34;对象重定位&#34;)。

必须有更好的方法来做这样的事情,我正在做的所有构建向量的东西都是附加的东西。例如,我可以有一个单独链接的块列表,并在最后将所有内容转换为单个向量,因此所有内容只需复制一次。

Boost或标准C ++库中有什么可以帮助解决这个问题吗?或者任何特别聪明的算法?

编辑:更具体:

struct SmallObject {
    unsigned id;
    boost::icl::discrete_interval<unsigned> ival;
};

1 个答案:

答案 0 :(得分:0)

哪个容器最有效的问题总是最好通过“依赖”和“测量它”来回答。

如果没有关于您的具体情况的更多信息,有两个“显而易见”的可能性:

使用链接列表

默认情况下,STL有两个链接列表:单链表std::forward_list和双链表std::deque。此外,std::list通常是双重连锁变体。文档中的一些引用:

  

std::forward [...]作为单链表实现,与C中的实现相比基本上没有任何开销。与std :: list相比,这个容器在双向时提供更节省空间的存储空间不需要迭代。

     

std::list [...]通常被实现为双向链表。与std :: forward_list相比,此容器提供双向迭代功能,同时节省空间。

     

std::deque(双端队列)[..]在双端队列的任何一端插入和删除都不会使指针或对其余元素的引用无效。

     

与std :: vector相反,双端队列的元素不是连续存储的:典型的实现使用一系列单独分配的固定大小的数组

在向量中保留空间

如果有任何方法可以估算出您想要存储的对象数量的上限,您可以提前使用reserve某个空格。

例如,如果您正在从文件中读取这些对象,则对象数量最多可以是文件大小除以16,或者行数乘以2,或者您可以进行一些其他快速简便的计算在构建这些对象之前做。

在这种情况下,如果您reserve容量,您将分配太多内存但阻止移动。即使上限有点太低,也没关系:你可能仍需要将容量加倍一次或两次,但至少你要防止所有的小幅增加(2 - > 4 - > 10 - > 16)循环的开始。