我正在使用队列和优先级队列,我计划通过这些队列很快地抽取大量数据。
因此,我希望我的q和pq能够对增加和减少做出反应。
使用vector,list或deque作为底层容器的相对优点是什么?
更新 在撰写本文时,Mike Seymour和Steve Townsend的答案都值得一读。谢谢他们!
答案 0 :(得分:7)
在类似于预期用例的情况下,确定选择如何影响性能的唯一方法是测量它。也就是说,这里有一些观察:
std::queue
:
std::deque
通常是最佳选择;它以恒定的时间支持所有必要的操作,并随着它的增长以块的形式分配内存。std::list
也支持必要的操作,但由于内存分配更多,可能会更慢;在特殊情况下,您可以通过从专用对象池分配来获得良好的结果,但这并非完全直截了当。std::vector
无法使用,因为它没有pop_front()
操作;这样的操作会很慢,因为它必须移动所有剩余的元素。可能更快但灵活性更低的替代方法是在固定大小的阵列上实现循环缓冲区(例如std::array
或std::vector
,但不调整大小。您需要通过报告错误或分配更大的缓冲区并复制所有数据来处理填充的情况。
std::priority_queue
:
std::vector
通常是最佳选择;它以指数方式增长(减少内存分配的数量),并且是一个访问速度非常快的简单数据结构 - 迭代器可以简单地实现为指针的包装。std::deque
可能会变慢,因为它通常会线性增长(需要更多内存分配),并且访问比使用向量更复杂。std::list
无法使用,因为它不提供随机访问。总结一下 - 默认值通常是最佳选择,但如果速度确实很重要,那么请测量替代品。
答案 1 :(得分:4)
我会使用std::queue
作为基本队列(默认情况下至少是deque
上的包装器)。如果这对您不起作用,请做一些更特殊的事情。
std::priority_queue
也存在(默认情况下超过vector
),但添加的语义使您更有可能在此处滚动自己,具体取决于您针对特定访问模式观察到的性能。
vector
具有存储特性,使其非常不适合从数据集的前面删除。每当你pop_front
时,都要做很多事情。对于简单队列,请避免这种情况。
list
可能过于昂贵,因为通过合同它必须提供你不需要的功能。它可能是用作优先级队列的候选者,但我的直觉总是信任STL。
答案 2 :(得分:3)
vector
将实现堆栈,因为快速插入结束,快速删除也在最后。如果您想要FIFO队列,vector
将是错误的实现。
deque
或list
都会在两端提供恒定的时间插入。 list
适用于LRU缓存,在这些缓存中,您希望将元素从中间快速移出,并且无论移动多少,您希望迭代器保持有效。通常在插入和删除结束时使用deque
。
我需要询问的关于你的集合的主要问题是它们是否被多个线程访问。我认为它们是,在这种情况下,你的主要目标之一是减少锁定。如果您至少拥有multi_push和multi_get功能,那么最好这样做,这样您就可以一次打开多个元素而无需任何锁定。
还有无锁容器或半无锁容器。
只要您的操作都是固定时间,您可能会发现锁定策略比集合本身的任何性能更重要。