C++ 我应该使用哪个STL容器作为FIFO?
哪个STL容器最适合我的需要?我基本上有一个10个元素宽的容器,在这个容器中我不断地向后推新元素,同时向前推最古老的元素(大约一百万次) 我目前正在使用C++ 我应该使用哪个STL容器作为FIFO?,c++,stl,fifo,C++,Stl,Fifo,哪个STL容器最适合我的需要?我基本上有一个10个元素宽的容器,在这个容器中我不断地向后推新元素,同时向前推最古老的元素(大约一百万次) 我目前正在使用std::deque来完成任务,但我想知道std::list是否会更有效,因为我不需要重新分配它自己(或者我可能把std::deque误认为是std::vector?)。还是有更有效的容器满足我的需要 另外,我不需要随机访问A可能比A更简单,但对于这样一个小列表,性能上的差异可能可以忽略不计 同样的情况也会发生。这取决于您想要什么API。请查看s
std::deque
来完成任务,但我想知道std::list
是否会更有效,因为我不需要重新分配它自己(或者我可能把std::deque
误认为是std::vector
?)。还是有更有效的容器满足我的需要
另外,我不需要随机访问A可能比A更简单,但对于这样一个小列表,性能上的差异可能可以忽略不计
同样的情况也会发生。这取决于您想要什么API。请查看
std::queue
。它包装一个底层容器类型,默认容器是std::deque
为什么不std::queue
?它所能做的就是向后推
和向前推
我不断地推回新元素
而pop_front
ing最旧的元素
(大约一百万次)
在计算机领域,一百万真的不是一个大数字。正如其他人所建议的,使用std::queue
作为第一个解决方案。如果速度太慢,请使用探查器(不要猜测!)确定瓶颈,并使用具有相同接口的不同容器重新实现。由于答案很多,您可能会感到困惑,但总结一下:
使用一个。原因很简单:它是FIFO结构。如果需要FIFO,可以使用std::queue
这会让别人,甚至你自己都清楚你的意图。A或不。列表可以在任何地方插入和删除,这不是FIFO结构应该做的,而deque
可以在任意一端添加和删除,这也是FIFO结构不能做的
这就是为什么您应该使用队列
现在,你问了关于性能的问题。首先,请始终记住这条重要的经验法则:先编写好代码,后执行性能。
原因很简单:在追求清洁和优雅之前追求表现的人几乎总是最后完成。他们的代码变得乱七八糟,因为他们放弃了一切好的东西,只是为了真正从中一无所获
通过先编写好的、可读的代码,大多数性能问题都会自行解决。如果以后发现性能不足,现在可以很容易地在漂亮、干净的代码中添加分析器,并找出问题所在
总之,std::queue
只是一个适配器。它提供了安全接口,但在内部使用了不同的容器。您可以选择这个底层容器,这允许很大的灵活性
那么,您应该使用哪个底层容器呢?我们知道std::list
和std::deque
都提供了必要的功能(push_-back()
、pop_-front()
)和front()
),那么我们如何决定呢
首先,要明白分配(和取消分配)内存通常不是一件容易的事情,因为它涉及到操作系统并要求它做一些事情。列表
必须在每次添加某个内容时分配内存,并在该内容消失时取消分配
另一方面,deque
,以块的形式进行分配。它的分配频率将低于列表
。可以将其视为一个列表,但每个内存块可以容纳多个节点。(当然,我建议你。)
因此,仅凭这一点,deque
就应该表现得更好,因为它不经常处理内存。再加上您正在处理的数据大小不变,在第一次传递数据之后,它可能不必进行分配,而列表将不断地进行分配和解除分配
第二件需要理解的事情是。进入RAM的速度很慢,所以当CPU真的需要时,它会充分利用这段时间,将一大块内存带回到缓存中。由于deque
在内存中分配块,因此访问此容器中的元素很可能会导致CPU返回容器的其余部分。现在,对deque
的任何进一步访问都会很快,因为数据在缓存中
这与列表不同,列表中的数据一次分配一个。这意味着数据可能分布在内存中的所有位置,缓存性能将很差
因此,考虑到这一点,一个deque
应该是一个更好的选择。这就是为什么在使用队列时它是默认容器的原因。尽管如此,这仍然只是一个(非常)有教育意义的猜测:你必须分析这段代码,在一个测试中使用deque
,在另一个测试中使用list
,才能真正确定
但请记住:让代码使用干净的界面,然后再担心性能
John提出了一个问题,即包装列表
或deque将导致性能下降。再一次,他和我都可以肯定地说,不需要自己分析它,但编译器很可能会内联队列
发出的调用。也就是说,当您说queue.push()
,它实际上只会说queue.container.push\u back()
,完全跳过函数调用
同样,这只是一个有根据的猜测,但是与使用底层容器raw相比,使用队列将不会降低性能。正如我之前所说,使用队列
,因为它干净、易于使用且安全,如果它真的成为一个问题配置文件和测试。在性能真正重要的地方,请查看。使用标准::队列
,但要注意
// FIFO with circular buffer
#define fifo_size 4
class Fifo {
uint8_t buff[fifo_size];
int writePtr = 0;
int readPtr = 0;
public:
void put(uint8_t val) {
buff[writePtr%fifo_size] = val;
writePtr++;
}
uint8_t get() {
uint8_t val = NULL;
if(readPtr < writePtr) {
val = buff[readPtr%fifo_size];
readPtr++;
// reset pointers to avoid overflow
if(readPtr > fifo_size) {
writePtr = writePtr%fifo_size;
readPtr = readPtr%fifo_size;
}
}
return val;
}
int count() { return (writePtr - readPtr);}
};