我希望能够使用缓冲区的一部分,直到它为空。我在下面设计了我自己的,但是我想知道std库中是否已经有这样的东西了,所以我去掉了实现我自己错误的可能性。
注意,我只将std::vector<T>
用于自动存储。我不做push_back
插入和pop_back
消耗,因为我想让数据消耗尽可能快。
#include <iostream>
#include <vector>
using namespace std;
template <class T>
class Buffer
{
public:
void write(T* buffer, size_t amountToWrite) {
if (amountToWrite <= this->_buffer.capacity()) {
std::copy(buffer, buffer + amountToWrite, this->_buffer.data());
_size += amountToWrite;
} else {
//In fact I wanted to increase capacity, not size. However we don't use the vector functions, so does it mater?
this->_buffer.resize(amountToWrite);
std::copy(buffer, buffer + amountToWrite, this->_buffer.data());
_size += amountToWrite;
}
}
size_t consume(T* bufferToWrite, size_t amountToConsume) {
if (_current==_size) {
//this means we've already read everything. Maybe we should throw or just return 0?
return 0;
}
if (amountToConsume <= this->_size) {
std::copy(this->_buffer.data() + _current, this->_buffer.data() + _current + amountToConsume, bufferToWrite);
_current += amountToConsume;
return amountToConsume;
} else {
size_t remaining = this->_size - amountToConsume;
std::copy(this->_buffer.data() + _current, this->_buffer.data() + _current + remaining, bufferToWrite);
_current += remaining;
return remaining;
}
}
private:
size_t _size = 0;
std::vector<T> _buffer;
size_t _current = 0;
};
int main()
{
Buffer<uint8_t> b;
uint8_t u[] = {1,2,3,4,5,6};
b.write(u, 6);
uint8_t r[3];
size_t consumedBytes = b.consume(r, 3);
std::cout << "consumed " << consumedBytes << std::endl;
for(int i=0; i<3; i++) {
std::cout << (int) r[i];
}
std::cout << std::endl;
size_t consumedBytes2 = b.consume(r, 3);
std::cout << "consumed " << consumedBytes2 << std::endl;
for(int i=0; i<3; i++) {
std::cout << (int) r[i];
}
std::cout << std::endl;
size_t consumedBytes3 = b.consume(r, 3);
std::cout << "consumed " << consumedBytes3 << std::endl;
return 0;
}
你觉得我的实现有什么问题吗?
我想做最安全的事情,同时使它快速。
我认为您可以利用从STL中使用dequeue。它实现了一个双重链表,您可以从它的一边读取,从另一边写入。点击此链接获取更多详细说明。
另一个最好的缓冲区实现是循环缓冲区实现。
我为循环缓冲区留下了一个c++实现代码。
class MyCircularQueue {
vector<int> mem;
int front;
int rear;
int len;
int cnt;
public:
MyCircularQueue(int k) {
len = k;
mem = vector<int> (k);
front = 0;
rear = -1;
cnt=0;
}
bool enQueue(int value) {
if(isFull())
return false;
rear = (rear+1) %len;
mem[rear]= value;
cnt++;
return true;
}
bool deQueue() {
if (isEmpty())
return false;
front = (front+1) % len;
cnt--;
return true;
}
int Front() {
if (isEmpty())
return -1;
return mem[front];
}
int Rear() {
if (isEmpty())
return -1;
return mem[rear];
}
bool isEmpty() {
return (cnt ==0);
}
bool isFull() {
return ( cnt == len);
}
};