C++如何实现一个循环缓冲区(Ring Buffer)?C++高效数据结构实战【性能编程】

admin 百科 18
RingBuffer模板实现SPSC无锁循环缓冲区,使用vector预分配内存、模运算/位运算处理边界、move语义避免拷贝,支持push/pop/size/capacity等操作,兼顾高性能与零内存泄漏。

C++如何实现一个循环缓冲区(Ring Buffer)?C++高效数据结构实战【性能编程】-第1张图片-佛山资讯网

用C++实现一个高性能、线程安全(可选)、无内存泄漏的循环缓冲区,核心在于正确管理读写索引、避免拷贝、利用模运算或位运算做边界处理,并支持常用操作如 push、pop、size、capacity。

基础模板实现(单生产者单消费者,无锁)

这是最常用、性能最高的场景。使用两个原子索引(或普通 int,若已保证单线程读/写),配合模运算实现环形逻辑:

template<typename T>
class RingBuffer {
    std::vector<T> buffer_;
    size_t capacity_;
    size_t head_ = 0;  // 下一个读取位置(消费者)
    size_t tail_ = 0;  // 下一个写入位置(生产者)
<p>public:
explicit RingBuffer(size<em>t capacity) : capacity</em>(capacity), buffer_(capacity) {}</p><pre class="brush:php;toolbar:false;">bool push(const T& item) {
    if (full()) return false;
    buffer_[tail_] = item;
    tail_ = (tail_ + 1) % capacity_;
    return true;
}

bool pop(T& item) {
    if (empty()) return false;
    item = std::move(buffer_[head_]);
    head_ = (head_ + 1) % capacity_;
    return true;
}

bool empty() const { return head_ == tail_; }
bool full()  const { return (tail_ + 1) % capacity_ == head_; }
size_t size() const { 
    return (tail_ >= head_) ? (tail_ - head_) : (capacity_ - head_ + tail_);
}
size_t capacity() const { return capacity_; }

登录后复制

};

✅ 关键点:
• 使用 std::vector 预分配连续内存,零额外分配开销
模运算 实现环形索引,清晰易懂;若容量为 2 的幂,可用 tail_ & (capacity_-1) 替代模运算加速
move 语义 在 pop 中避免冗余拷贝(尤其对大对象)

无锁优化:使用原子变量 + 内存序(SPSC 场景)

当明确只有 1 个线程 push、1 个线程 pop 时,可将 head_tail_ 改为 std::atomic_size_t,并用 relaxed 内存序提升性能:

立即学习“C++免费学习笔记(深入)”;

标签: ai c++ 无锁

发布评论 0条评论)

还木有评论哦,快来抢沙发吧~