环形队列判空为front == rear,判满为(rear + 1) % n == front,需牺牲一个空间;用std::vector时应构造固定大小避免重分配;不可用std::queue/std::deque模拟环形;多线程下spsc可用原子变量,mpmc需锁或无锁算法。

环形队列的核心判空判满逻辑怎么写
环形队列的关键不在“循环”,而在如何区分 front == rear 时到底是空还是满。最常用且安全的做法是**牺牲一个元素空间**:容量为 N 的数组,只存最多 N-1 个元素。此时:
– 判空:front == rear
– 判满:(rear + 1) % N == front
不用额外计数器,也不依赖标志位,避免了多线程下标志位不同步的风险。
用 std::vector 实现时要注意哪些内存细节
直接用 std::vector<t></t> 存数据没问题,但必须在构造时明确预留空间(resize(N) 或 reserve(N)),否则后续 push_back 会触发重分配,导致所有指针/索引失效。更稳妥的是用 std::vector<t>(N)</t> 构造固定大小容器,再用下标访问模拟环形行为:
class CircularQueue {
std::vector<int> buf;
size_t front_, rear_, cap_;
public:
CircularQueue(size_t n) : buf(n), front_(0), rear_(0), cap_(n) {}
bool push(int x) {
if ((rear_ + 1) % cap_ == front_) return false; // 满
buf[rear_] = x;
rear_ = (rear_ + 1) % cap_;
return true;
}
};
为什么不要用 std::queue 直接套 std::deque 模拟环形
std::queue 是适配器,底层虽可用 std::deque,但它不提供随机访问和容量控制接口,无法高效实现环形语义中的“头尾索引计算”和“判满”。更严重的是:std::deque 内部是分段连续内存,size() 和迭代器操作开销不稳定,且无法保证物理上“首尾相邻”——这会让“取模绕回”失去意义。真要复用 STL,应选 std::array 或裸 new T[N] 配合手动索引。
多线程环境下读写冲突怎么处理
单生产者单消费者(SPSC)场景下,可仅用 std::atomic<size_t></size_t> 管理 front_ 和 rear_,无需锁;但多对多(MPMC)必须加锁或用无锁算法(如基于 CAS 的双原子变量)。注意:即使用了原子操作,仍需确保 buf 的读写不越界、不重叠,且编译器不会因优化打乱内存顺序——建议在关键位置加 std::memory_order_acquire/std::memory_order_release。
立即学习“C++免费学习笔记(深入)”;
环形队列真正难的不是代码长度,而是边界条件是否覆盖全、多线程下内存序是否显式约束、以及 resize 时旧数据能否平滑迁移——这些地方一错,问题往往延迟暴露,且难以复现。











