C++ 模板化环形缓冲区实现:如何单独声明和初始化它?
C++ templated ring buffer implementation: how to declare and initialize it separately?
我在 github 上发现了 this 带有互斥锁的环形缓冲区的实现。我贴上代码给你看:
#include <cstdio>
#include <memory>
#include <mutex>
template <class T>
class circular_buffer {
public:
explicit circular_buffer(size_t size) :
buf_(std::unique_ptr<T[]>(new T[size])),
max_size_(size)
{
}
void put(T item)
{
std::lock_guard<std::mutex> lock(mutex_);
buf_[head_] = item;
if(full_)
{
tail_ = (tail_ + 1) % max_size_;
}
head_ = (head_ + 1) % max_size_;
full_ = head_ == tail_;
}
T get()
{
std::lock_guard<std::mutex> lock(mutex_);
if(empty())
{
return T();
}
//Read data and advance the tail (we now have a free space)
auto val = buf_[tail_];
full_ = false;
tail_ = (tail_ + 1) % max_size_;
return val;
}
void reset()
{
std::lock_guard<std::mutex> lock(mutex_);
head_ = tail_;
full_ = false;
}
bool empty() const
{
//if head and tail are equal, we are empty
return (!full_ && (head_ == tail_));
}
bool full() const
{
//If tail is ahead the head by 1, we are full
return full_;
}
size_t capacity() const
{
return max_size_;
}
size_t size() const
{
size_t size = max_size_;
if(!full_)
{
if(head_ >= tail_)
{
size = head_ - tail_;
}
else
{
size = max_size_ + head_ - tail_;
}
}
return size;
}
private:
std::mutex mutex_;
std::unique_ptr<T[]> buf_;
size_t head_ = 0;
size_t tail_ = 0;
const size_t max_size_;
bool full_ = 0;
};
int main(void)
{
circular_buffer<uint32_t> circle(10);
printf("\n === CPP Circular buffer check ===\n");
printf("Size: %zu, Capacity: %zu\n", circle.size(), circle.capacity());
uint32_t x = 1;
printf("Put 1, val: %d\n", x);
circle.put(x);
x = circle.get();
printf("Popped: %d\n", x);
printf("Empty: %d\n", circle.empty());
printf("Adding %zu values\n", circle.capacity() - 1);
for(uint32_t i = 0; i < circle.capacity() - 1; i++)
{
circle.put(i);
}
circle.reset();
printf("Full: %d\n", circle.full());
printf("Adding %zu values\n", circle.capacity());
for(uint32_t i = 0; i < circle.capacity(); i++)
{
circle.put(i);
}
printf("Full: %d\n", circle.full());
printf("Reading back values: ");
while(!circle.empty())
{
printf("%u ", circle.get());
}
printf("\n");
printf("Adding 15 values\n");
for(uint32_t i = 0; i < circle.size() + 5; i++)
{
circle.put(i);
}
printf("Full: %d\n", circle.full());
printf("Reading back values: ");
while(!circle.empty())
{
printf("%u ", circle.get());
}
printf("\n");
printf("Empty: %d\n", circle.empty());
printf("Full: %d\n", circle.full());
return 0;
}
在代码块的末尾,您可以找到带有示例的主函数。在那里,队列用 space 初始化为 10 个元素,如
circular_buffer<uint32_t> circle(10);
因为我想将其中一个环形缓冲区用作另一个 class 中的对象进行测试,我一直在尝试声明缓冲区,然后使用指示大小的变量对其进行初始化。这只是我想要完成的一个例子,就像通常在 java:
中所做的那样
int size = 20;
circular_buffer<uint16_t> ring;
ring = new circular_buffer<uint16_t>(size);
到目前为止我试过的所有东西都不编译。在 C++ 中使用模板化 class 这可能吗?
谢谢。
您已在具有自动存储期限的堆栈上声明 ring
。这不是一个指针:
circular_buffer<uint16_t> ring;
但随后您尝试使用 new
在堆上动态构造它,它期望 ring
是指针类型(例如 circular_buffer<uint16_t>* ring;
)
你的示例中不需要动态分配,直接构造即可:
int size = 20;
circular_buffer<uint16_t> ring{size};
我在 github 上发现了 this 带有互斥锁的环形缓冲区的实现。我贴上代码给你看:
#include <cstdio>
#include <memory>
#include <mutex>
template <class T>
class circular_buffer {
public:
explicit circular_buffer(size_t size) :
buf_(std::unique_ptr<T[]>(new T[size])),
max_size_(size)
{
}
void put(T item)
{
std::lock_guard<std::mutex> lock(mutex_);
buf_[head_] = item;
if(full_)
{
tail_ = (tail_ + 1) % max_size_;
}
head_ = (head_ + 1) % max_size_;
full_ = head_ == tail_;
}
T get()
{
std::lock_guard<std::mutex> lock(mutex_);
if(empty())
{
return T();
}
//Read data and advance the tail (we now have a free space)
auto val = buf_[tail_];
full_ = false;
tail_ = (tail_ + 1) % max_size_;
return val;
}
void reset()
{
std::lock_guard<std::mutex> lock(mutex_);
head_ = tail_;
full_ = false;
}
bool empty() const
{
//if head and tail are equal, we are empty
return (!full_ && (head_ == tail_));
}
bool full() const
{
//If tail is ahead the head by 1, we are full
return full_;
}
size_t capacity() const
{
return max_size_;
}
size_t size() const
{
size_t size = max_size_;
if(!full_)
{
if(head_ >= tail_)
{
size = head_ - tail_;
}
else
{
size = max_size_ + head_ - tail_;
}
}
return size;
}
private:
std::mutex mutex_;
std::unique_ptr<T[]> buf_;
size_t head_ = 0;
size_t tail_ = 0;
const size_t max_size_;
bool full_ = 0;
};
int main(void)
{
circular_buffer<uint32_t> circle(10);
printf("\n === CPP Circular buffer check ===\n");
printf("Size: %zu, Capacity: %zu\n", circle.size(), circle.capacity());
uint32_t x = 1;
printf("Put 1, val: %d\n", x);
circle.put(x);
x = circle.get();
printf("Popped: %d\n", x);
printf("Empty: %d\n", circle.empty());
printf("Adding %zu values\n", circle.capacity() - 1);
for(uint32_t i = 0; i < circle.capacity() - 1; i++)
{
circle.put(i);
}
circle.reset();
printf("Full: %d\n", circle.full());
printf("Adding %zu values\n", circle.capacity());
for(uint32_t i = 0; i < circle.capacity(); i++)
{
circle.put(i);
}
printf("Full: %d\n", circle.full());
printf("Reading back values: ");
while(!circle.empty())
{
printf("%u ", circle.get());
}
printf("\n");
printf("Adding 15 values\n");
for(uint32_t i = 0; i < circle.size() + 5; i++)
{
circle.put(i);
}
printf("Full: %d\n", circle.full());
printf("Reading back values: ");
while(!circle.empty())
{
printf("%u ", circle.get());
}
printf("\n");
printf("Empty: %d\n", circle.empty());
printf("Full: %d\n", circle.full());
return 0;
}
在代码块的末尾,您可以找到带有示例的主函数。在那里,队列用 space 初始化为 10 个元素,如
circular_buffer<uint32_t> circle(10);
因为我想将其中一个环形缓冲区用作另一个 class 中的对象进行测试,我一直在尝试声明缓冲区,然后使用指示大小的变量对其进行初始化。这只是我想要完成的一个例子,就像通常在 java:
中所做的那样int size = 20;
circular_buffer<uint16_t> ring;
ring = new circular_buffer<uint16_t>(size);
到目前为止我试过的所有东西都不编译。在 C++ 中使用模板化 class 这可能吗?
谢谢。
您已在具有自动存储期限的堆栈上声明 ring
。这不是一个指针:
circular_buffer<uint16_t> ring;
但随后您尝试使用 new
在堆上动态构造它,它期望 ring
是指针类型(例如 circular_buffer<uint16_t>* ring;
)
你的示例中不需要动态分配,直接构造即可:
int size = 20;
circular_buffer<uint16_t> ring{size};