C++ 固定容量环形队列实现

1. 适用场景

这种写法适合高频数据流(如视频帧、传感器数据):

  • 需要固定内存上限,避免队列无限增长
  • 希望减少频繁 new/delete 带来的抖动
  • 允许拥塞时丢帧(例如"丢旧保新"以降低时延)

2. 核心思路

底层用固定长度 vector<unique_ptr<T>> 作为槽位池,再配合三个状态量:

  • head:下次入队写入位置(写指针)
  • tail:下次出队读取位置(读指针)
  • size:当前有效元素数量

"环形"靠取模实现:

idx = (idx + 1) % capacity

这样索引走到末尾会回到 0,不需要搬移元素。


3. 两种满队列策略

A. 满了丢新(Reject-New)

  • 队列满时直接返回失败
  • 不覆盖队列中已有数据
  • 简单直观,但可能导致"新数据进不来"

B. 满了丢旧(Keep-Latest)

  • 队列满时仍接收新数据
  • 通过前移 tail 丢弃最老元素
  • 更适合实时场景,减少处理过期数据的概率

4. 简化示例(独立可编译)

cpp 复制代码
#include <iostream>
#include <memory>
#include <vector>

struct Frame {
  int id = -1;
};

class RingQueue {
 public:
  explicit RingQueue(size_t capacity) : buf_(capacity), capacity_(capacity) {
    for (size_t i = 0; i < capacity_; ++i) {
      buf_[i] = std::make_unique<Frame>();  // 预分配槽位对象
    }
  }

  // 满了丢新
  bool PushRejectNew(std::unique_ptr<Frame>& in) {
    if (size_ >= capacity_) return false;
    std::swap(buf_[head_], in);             // O(1) 交换所有权
    head_ = (head_ + 1) % capacity_;
    ++size_;
    return true;
  }

  // 满了丢旧,保留最新
  bool PushKeepLatest(std::unique_ptr<Frame>& in, bool* overwrote_oldest = nullptr) {
    bool overwritten = false;
    std::swap(buf_[head_], in);
    head_ = (head_ + 1) % capacity_;

    if (size_ >= capacity_) {
      tail_ = (tail_ + 1) % capacity_;      // 丢最老元素
      overwritten = true;
    } else {
      ++size_;
    }

    if (overwrote_oldest) *overwrote_oldest = overwritten;
    return true;
  }

  bool Pop(std::unique_ptr<Frame>& out) {
    if (size_ == 0) return false;
    std::swap(buf_[tail_], out);
    tail_ = (tail_ + 1) % capacity_;
    --size_;
    return true;
  }

 private:
  std::vector<std::unique_ptr<Frame>> buf_;
  size_t capacity_{0};
  size_t head_{0};
  size_t tail_{0};
  size_t size_{0};
};

5. 为什么 swap 能提效

  • 不做大对象拷贝,只交换 unique_ptr 所有权
  • 减少动态分配/释放次数,降低内存碎片风险
  • 延迟抖动更小,实时性更稳定

6. 实战注意点

  • 多线程场景必须加锁(或使用无锁结构)
  • 队列容量过小会导致覆盖/丢帧频繁
  • 建议监控:队列长度、覆盖次数、端到端时延

7. 一句话总结

vector + 环形索引 + swap 本质是"固定容量对象池 + 环形队列",

在实时系统中通常比通用动态队列更可控、更稳定。

相关推荐
hPw0eKIqD15 小时前
C++ 模板参数推导问题小记(非推导上下文)
开发语言·c++
程序员爱德华15 小时前
Python与C++:异同点对比
c++·python
普通攻击往后拉16 小时前
Leetcode 206. 反转链表
算法·leetcode·链表
@syh.16 小时前
【贪心】矩阵消除游戏
算法·游戏·矩阵
可编程芯片开发17 小时前
基于零极点配置的PID控制系统simulink建模与仿真
算法
徐小夕17 小时前
开源!我用SQLite + DuckDB打造了一款可视化AI问数平台
前端·算法·github
Hrain-AI17 小时前
2026 企业 AI 智能体平台横评:8 大主流平台 7 维度实测对比
人工智能·算法·机器学习
Angel Q.18 小时前
因子分析和生成模型有什么关系?从“幕后因素”到“生成数据”
算法
888CC++19 小时前
C语言与C++的区别:从面向过程到面向对象
java·c语言·c++