0

0

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

穿越時空

穿越時空

发布时间:2025-12-20 05:07:21

|

644人浏览过

|

来源于php中文网

原创

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

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

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

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

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

template
class RingBuffer {
    std::vector buffer_;
    size_t capacity_;
    size_t head_ = 0;  // 下一个读取位置(消费者)
    size_t tail_ = 0;  // 下一个写入位置(生产者)

public: explicit RingBuffer(sizet capacity) : capacity(capacity), buffer_(capacity) {}

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数字人平台

下载
  • push 中:用 tail_.fetch_add(1, std::memory_order_relaxed) 获取旧 tail,再取模写入
  • pop 中:用 head_.fetch_add(1, std::memory_order_relaxed) 获取旧 head,再取模读取
  • size 计算需注意:因 head/tail 异步更新,需先 load tail,再 load head,再重新 load tail 做 double-check(避免重排序导致误判)

支持多生产者/多消费者?谨慎上锁或换方案

MPMC 循环缓冲区天然复杂。强行加互斥锁(如 std::mutex)会严重拖慢吞吐。更推荐:

  • boost::lockfree::spsc_queuemoodycamel::ConcurrentQueue(工业级无锁队列)
  • 若必须手写 MPMC RingBuffer:需双原子索引 + 比较交换(CAS)+ “预留槽位”协议 + ABA 保护,实现难度高、易出错
  • 多数场景下,用多个 SPSC buffer + 负载分片,比单个 MPMC buffer 更快更稳

实用增强技巧(不增加复杂度)

让 RingBuffer 更好用、更健壮:

  • 支持范围写入:提供 reserve() + commit(size_t n) 接口,批量写入避免多次边界检查
  • 自动扩容策略:仅在调试模式启用,发布版保持固定容量——环形缓冲本意就是确定性延迟
  • 迭代器支持:可添加只读正向迭代器(按逻辑顺序遍历当前有效元素),方便调试和 STL 算法兼容
  • 零拷贝视图:对 POD 类型,提供 data_span() 返回 std::span,直接暴露底层内存块

基本上就这些。环形缓冲不是越复杂越好,而是越贴合场景越高效。SPSC 下几十行模板代码就能跑满内存带宽,远胜通用容器。关键在克制——明确约束,放弃通用,换来确定性性能。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

315

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

537

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

52

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

197

2025.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

52

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

98

2025.10.23

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

534

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

17

2025.12.22

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

36

2026.01.14

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号