环形缓冲区(Ring Buffer)具有类似于环形链表的特性,即当缓冲区的末尾被写满时,新的数据会从缓冲区的开头重新写入,实现循环复用。
其通常由一个固定大小的数组和两个指针组成:一个用于指向缓冲区的开头(读指针),一个用于指向缓冲区的末尾(写指针)。当需要向缓冲区写入数据时,数据先被写入当前写指针所指向的位置,然后写指针向后移动一格。当需要从缓冲区读取数据时,数据被读取当前读指针所指向的位置,然后读指针向后移动一格。
下面是自己实现一个RingBuffer。
#include <iostream>
template <typename T>
class RingBuffer {
public:
RingBuffer(int size): head(0), tail(0), size(size)
{//构造函数
buffer = new T[size];
}
~RingBuffer()
{//析构函数
delete[] buffer;
}
RingBuffer(const RingBuffer& other) : head(other.head), tail(other.tail), size(other.size)
{//拷贝构造函数
buffer = new T[size];
memcpy(buffer, other.buffer, size * sizeof(T));
}
RingBuffer& operator=(const RingBuffer& other)
{//拷贝赋值运算符
if (this != &other)
{
delete[] buffer;
head = other.head;
tail = other.tail;
size = other.size;
buffer = new T[size];
memcpy(buffer, other.buffer, size * sizeof(T));
}
return *this;
}
RingBuffer(RingBuffer&& other) noexcept : head(other.head), tail(other.tail), size(other.size), buffer(other.buffer)
{//移动构造函数
other.head = 0;
other.tail = 0;
other.size = 0;
other.buffer = nullptr;
}
RingBuffer& operator=(RingBuffer&& other) noexcept
{//移动赋值运算符
if(this != &other)
{
delete[] buffer;
head = other.head;
tail = other.tail;
size = other.size;
buffer = other.buffer;
other.head = 0;
other.tail = 0;
other.size = 0;
other.buffer = nullptr;
}
return *this;
}
void push(T value)
{
buffer[tail] = std::move(value);
tail = (tail + 1) % size;;
if(tail == head)
{//如果首尾相等,则丢掉当前元素,头部往前一格
head = (head + 1) % size;
}
}
T pop()
{
if(head == tail)
{
std::cout << "buffer is empty!" << std::endl;
return T();
}
T value = std::move(buffer[head]);
head = (head + 1) % size;
return value;
}
private:
T* buffer;
int head;
int tail;
int size;
};