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 本质是"固定容量对象池 + 环形队列",

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

相关推荐
im_AMBER2 小时前
手撕hot100之矩阵!看完这篇就AC~
javascript·数据结构·线性代数·算法·leetcode·矩阵
笨笨饿2 小时前
#79_NOP()嵌入式C语言中内联汇编宏的抽象封装模式研究
linux·c语言·网络·驱动开发·算法·硬件工程·个人开发
wxin_VXbishe3 小时前
springboot新能源车充电站管理系统小程序-计算机毕业设计源码29213
java·c++·spring boot·python·spring·django·php
风萧萧19993 小时前
问答样例如何在RAG问答中使用?
算法
七夜zippoe3 小时前
DolphinDB分区策略:HASH分区与COMPO分区
算法·哈希算法·hash·dolphindb·compo
沪漂阿龙4 小时前
程序员面试技术爆款文:2026大厂算法通关手册——从零基础到LeetCode刷穿,这一篇就够了
算法·leetcode·面试
05候补工程师4 小时前
【408 从零到一】线性表逻辑特征、存储结构对比与 C/C++ 动态内存分配避坑指南
c语言·开发语言·数据结构·c++·考研
rit84324994 小时前
基于博弈论的小区分簇算法MATLAB实现
开发语言·算法·matlab
华清远见成都中心4 小时前
C 语言内存管理深度解析:malloc/free 与嵌入式堆栈分配策略
java·c语言·算法