0

0

c++如何实现一个环形缓冲区 c++ Ring Buffer数据结构【实例】

穿越時空

穿越時空

发布时间:2025-12-27 16:57:07

|

501人浏览过

|

来源于php中文网

原创

环形缓冲区用固定数组加读写索引与取模实现首尾相连,采用“预留空位法”判空满:空为read_idx==write_idx,满为(write_idx+1)%capacity==read_idx。

c++如何实现一个环形缓冲区 c++ ring buffer数据结构【实例】

用 C++ 实现环形缓冲区(Ring Buffer),核心是用固定大小的数组配合两个索引(读位置 read_idx 和写位置 write_idx),通过取模运算实现“首尾相连”的效果。关键在于正确处理空/满判断、线程安全(如需)、以及边界更新逻辑。

基础单生产者-单消费者版本(无锁,适合简单场景)

这是最常用、最易理解的实现。使用 std::array 或原始数组 + 模运算,用“预留一个空位”方式区分空与满(即容量为 N 的缓冲区最多存 N-1 个元素):

  • 空: read_idx == write_idx
  • 满: (write_idx + 1) % capacity == read_idx
  • 写入后: write_idx = (write_idx + 1) % capacity
  • 读出后: read_idx = (read_idx + 1) % capacity

示例代码(C++17):

template 
class RingBuffer {
    std::array buffer_;
    size_t read_idx_ = 0;
    size_t write_idx_ = 0;

public: bool push(const T& item) { size_t next_write = (writeidx + 1) % N; if (next_write == readidx) return false; // 已满 buffer_[writeidx] = item; writeidx = next_write; return true; }

bool pop(T& item) {
    if (read_idx_ == write_idx_) return false; // 为空
    item = std::move(buffer_[read_idx_]);
    read_idx_ = (read_idx_ + 1) % N;
    return true;
}

size_t size() const { 
    return (write_idx_ - read_idx_ + N) % N; 
}
bool empty() const { return read_idx_ == write_idx_; }
bool full() const { return (write_idx_ + 1) % N == read_idx_; }

};

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

Faceswap
Faceswap

免费开源的AI换脸工具

下载

支持任意长度、带异常安全的版本(使用 vector + capacity)

若需要运行时指定大小,或希望更贴近 STL 风格(如支持 front()back()),可用 std::vector 替代 std::array,并封装构造函数:

  • 构造时传入容量,内部分配 capacity_ + 1 空间(仍采用“空位法”判满)
  • 所有操作加 noexcept 标记(除构造可能抛异常外)
  • 提供 try_push / try_pop 接口,避免异常路径

线程安全版本(SPSC 或 MPSC 场景)

多线程下需避免竞态。常见做法:

  • SPSC(单生产单消费):用 std::atomic 管理 read_idx_write_idx_,配合 memory_order_acquire/release,无需锁,性能极高
  • MPSC(多生产单消费):写入端需原子 CAS 更新 write_idx_,或用细粒度锁保护写索引
  • 注意:不要直接对缓冲区数组做原子操作;索引是原子的,数据拷贝本身不是原子的,但只要不越界、不重叠,就是安全的

实用增强建议

  • 添加 reserve()capacity() 接口,明确暴露底层容量语义
  • 支持迭代器(可选):让 begin()/end() 返回按逻辑顺序遍历的迭代器(需跳过未填充区域)
  • 提供批量读写接口(如 push_npop_n),减少循环开销
  • 调试时可启用断言(如检查索引是否始终

环形缓冲区不复杂但容易忽略边界细节。从“空位法”入手,再逐步加原子性或泛型支持,就能写出健壮、高效、易用的 Ring Buffer。

相关专题

更多
treenode的用法
treenode的用法

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

529

2023.12.01

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

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

4

2025.12.22

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

985

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

41

2025.10.17

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

465

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

22

2025.12.24

ip地址修改教程大全
ip地址修改教程大全

本专题整合了ip地址修改教程大全,阅读下面的文章自行寻找合适的解决教程。

35

2025.12.26

压缩文件加密教程汇总
压缩文件加密教程汇总

本专题整合了压缩文件加密教程,阅读专题下面的文章了解更多详细教程。

18

2025.12.26

wifi无ip分配
wifi无ip分配

本专题整合了wifi无ip分配相关教程,阅读专题下面的文章了解更多详细教程。

46

2025.12.26

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 5.4万人学习

C 教程
C 教程

共75课时 | 3.7万人学习

C++教程
C++教程

共115课时 | 10.1万人学习

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

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