在 C++ 中,如何创建一个简单的固定大小队列?
首先,我认为您真正想要的是一个固定容量队列,即队列的大小本身将受限于队列的容量,但大小可能会有所不同。例如,如果队列为空,则大小最初可以为零,并在您将元素插入队列时增加到队列的容量。
使用boost::circular_buffer
Boost 库具有库 Boost.CircularBuffer,它实现了 boost::circular_buffer 容器 (boost/circular_buffer.hpp)。该容器适合作为固定容量的 FIFO。
与std::vector 不同,boost::circular_buffer 的容量 保持不变,无论您向容器中插入多少元素。也就是说,不会在后台发生重新分配:如果 boost::circular_buffer 的 size 达到其 容量,则插入新元素只会覆盖现有元素。
您可以在构造时指定boost::circular_buffer的容量:
boost::circular_buffer<int> cb(2);
cb 的容量为2,由于容器为空,其初始大小为零。它的大小永远不能超过它的容量。但是,您可以显式更改容器的容量,例如,通过调用 circular_buffer::set_capacity()。
通过使用push_back() 和pop_front() 成员函数,您可以将boost::circular_buffer 用作FIFO。示例:
#include <boost/circular_buffer.hpp>
#include <iostream>
void print(const boost::circular_buffer<int>& cb) {
std::cout << "size: " << cb.size() << ", capacity: " << cb.capacity() << '\n';
for (auto const& elem: cb)
std::cout << elem << ' ';
std::cout << '\n';
}
auto main() -> int {
// empty: size is zero
boost::circular_buffer<int> cb(3);
print(q);
cb.push_back(0);
print(cb);
cb.push_back(1);
print(cb);
cb.push_back(2);
print(cb);
// overwrites the oldest element: 0
cb.push_back(3);
print(cb);
// overwrites the oldest element: 1
cb.push_back(4);
print(cb);
cb.pop_front();
print(cb);
cb.pop_front();
print(cb);
// empty again
cb.pop_front();
print(cb);
}
输出:
size: 0, capacity: 3
size: 1, capacity: 3
0
size: 2, capacity: 3
0 1
size: 3, capacity: 3
0 1 2
size: 3, capacity: 3
1 2 3
size: 3, capacity: 3
2 3 4
size: 2, capacity: 3
3 4
size: 1, capacity: 3
4
size: 0, capacity: 3
使用std::queue 和boost::circular_buffer
std::queue 是一个容器适配器,其底层容器默认为std::deque。但是,您可以将boost::circular_buffer 用作std::queue 的底层容器,因为它实现了front()、back()、push_back() 和pop_front() 成员函数:
#include <queue>
#include <boost/circular_buffer.hpp>
#include <cassert>
template<typename T>
using FixedCapacityQueue = std::queue<T, boost::circular_buffer<T>>;
auto main() -> int {
FixedCapacityQueue<int> fixedCapQueue(boost::circular_buffer<int>(3));
fixedCapQueue.push(0);
fixedCapQueue.push(1);
fixedCapQueue.push(2);
fixedCapQueue.push(3); // overwrites the 0
assert(fixedCapQueue.front() == 1);
fixedCapQueue.pop(); // pops the 1
assert(fixedCapQueue.front() == 2);
}