Kai*_*zay 43 c++ buffering fifo data-stream c++11
有很多问题表明应该总是使用向量,但在我看来,列表对于场景更好,我们需要存储"最后n个项目"
例如,假设我们需要存储最后看到的5个项目:迭代0:
3,24,51,62,37,
Run Code Online (Sandbox Code Playgroud)
然后在每次迭代时,删除索引0处的项目,并在末尾添加新项目:
迭代1:
24,51,62,37,8
Run Code Online (Sandbox Code Playgroud)
迭代2:
51,62,37,8,12
Run Code Online (Sandbox Code Playgroud)
似乎对于这个用例,对于向量,复杂度将是O(n),因为我们必须复制n个项目,但是在列表中,它应该是O(1),因为我们总是只是砍掉了头部,并在每次迭代时添加到尾部.
我的理解是否正确?这是std :: list的实际行为吗?
Tae*_*myr 95
都不是.您的系列有固定的尺寸,std::array足够了.
您实现的数据结构称为环形缓冲区.要实现它,您需要创建一个数组并跟踪当前第一个元素的偏移量.
当您添加一个将项目推出缓冲区的元素时 - 即当您删除第一个元素时 - 您会增加偏移量.
要获取缓冲区中的元素,可以添加索引和偏移量,并获取此模数和缓冲区的长度.
Dav*_*ett 33
std :: deque是一个更好的选择.或者,如果您对std :: deque进行了基准测试并发现其性能不适合您的特定用途,则可以在固定大小的数组中实现循环缓冲区,并存储缓冲区起始的索引.替换缓冲区中的元素时,将覆盖起始索引处的元素,然后将起始索引设置为其先前的值加上缓冲区大小的模数.
列表遍历非常慢,因为列表元素可以分散在整个内存中,并且向量移位实际上非常快,因为即使存在大块,内存在单个内存块上移动也非常快.
讲座驯服野兽性能从会议C++ 2015年会议可能是你的兴趣.
man*_*lio 25
如果你可以使用Boost,试试boost :: circular_buffer:
这是一种类似于std::list或的序列std::deque.它支持随机访问迭代器,缓冲区开头或结尾的恒定时间插入和擦除操作以及与std算法的互操作性.
它提供固定容量存储:当缓冲区被填满时,从缓冲区的开头开始写入新数据并覆盖旧数据
// Create a circular buffer with a capacity for 5 integers.
boost::circular_buffer<int> cb(5);
// Insert elements into the buffer.
cb.push_back(3);
cb.push_back(24);
cb.push_back(51);
cb.push_back(62);
cb.push_back(37);
int a = cb[0]; // a == 3
int b = cb[1]; // b == 24
int c = cb[2]; // c == 51
// The buffer is full now, so pushing subsequent
// elements will overwrite the front-most elements.
cb.push_back(8); // overwrite 3 with 8
cb.push_back(12); // overwrite 24 with 12
// The buffer now contains 51, 62, 37, 8, 12.
// Elements can be popped from either the front or the back.
cb.pop_back(); // 12 is removed
cb.pop_front(); // 51 is removed
Run Code Online (Sandbox Code Playgroud)
所述circular_buffer存储其在存储器的连续区域,其然后能快速元件常数时间插入,删除和元件的随机接入.
PS ......或者按照Taemyr的建议直接实现循环缓冲.
Overload Journal#50 - 2002年8月有一个很好的介绍(由Pete Goodliffe编写)来编写强大的STL类循环缓冲区.
问题是O(n)只讨论渐近行为,因为n倾向于无穷大.如果n很小,则所涉及的常数因子变得显着.结果是,对于"最后5个整数项目",如果向量没有击败列表,我会被震惊.我甚std::vector至希望能够击败std::deque.
对于"最后500个整数项目",我仍然期望std::vector比std::list- 更快- 但std::deque现在可能会获胜.对于"最后500万个缓慢复制的项目",std:vector将是最慢的.
在环形缓冲区基于std::array或std::vector将可能更快还在虽然.
(几乎)始终存在性能问题:
在实践中,只要使用一个std::deque或预先构建的环形缓冲区(如果有的话),就足够了.(但是除非分析说你需要,否则不值得编写环形缓冲区.)