我想要一个简单而有效的循环缓冲区/队列。如果我使用std::vector
,我必须这样做:
if ( v.size() >= limit ) {
std::vector<int> it = v.begin();
v.insert( it, data );
v.erase( it+1 );
}
有没有更简单的解决方案?
答案 0 :(得分:11)
您希望保持缓冲区的大小,覆盖旧项目。随着时间的推移,只是覆盖旧的。如果你想处理nItems&lt;限制,那么你需要处理它,这只是一个使用modulo插入固定大小缓冲区的简单例子。
std::vector<int> data(10);
for (int i = 0 ; i < 100 ; ++i)
{
data[i%10] = i;
}
for (std::vector<int>::const_iterator it = data.begin() ; it !=data.end(); ++it)
{
std::cout << *it << std::endl;
}
这种插入方法会将最后10个元素保留在缓冲区中。
答案 1 :(得分:1)
std::list
可能比std::vector
更容易构建列表。还有std::queue
。
您使用向量来实现循环队列也很有趣,但是询问如何实施循环列表的问题。为什么不使用地图?
答案 2 :(得分:0)
尝试std :: deque。接口就像使用std :: vector,但在开头和结尾插入和删除更有效。
答案 3 :(得分:0)
在c++11
中,对于固定尺寸的替代方案,您应该使用std::array
:
const unsigned int BUFFER_SIZE = 10;
std::array<int, BUFFER_SIZE> buffer; // The buffer size is fixed at compile time.
for (i = 0; i < 100; ++i) {
buffer[i % BUFFER_SIZE] = i;
}
答案 4 :(得分:0)
您可以照常使用向量,然后创建一个get_element(index)函数以使其具有圆形感。因为它只是整数操作,所以它非常快速,简单。
template<typename T>
T get_element(std::vector<T> vec, int index) {
int vector_size = vec.size();
int vector_max = vector_size - 1;
int vector_min = 0;
int index_diff = 0;
int refined_index = 0;
// index_diff is the amount of index-out-of-range. Positive means index was
// bigger than the vector size, negative means index was smaller than 0
if (index > vector_max) {
index_diff = index - vector_max;
} else if (index < vector_min) {
index_diff = index;
} else {
index_diff = 0;
}
// Make the indexing feel circular
// index mod 16 yields a number from 0 to 15
if (index_diff > 0) {
refined_index = index % vector_size;
} else if (index_diff < 0) {
int temp_index = index % vector_size;
if (temp_index != 0) {
refined_index = vector_size - std::abs(temp_index);
// if the negative mod equals to 0, we can't have 16 - 0 = 16 index,
// so we set it to 0 manually
} else {
refined_index = 0;
}
} else {
refined_index = index;
}
return vec[refined_index];
}
然后像这样使用它:
int result = get_element<int>(myvec, 256);
请注意,任何小于0的索引都会从向量的最后一个元素开始旋转,这当然是有意的。