我被要求在C ++中实现一个循环缓冲区,该缓冲区采用未指定类型。我假设泛型类型是基本类型。 (或者它应该考虑非基本类型?)对于缓冲区,我使用基本数组,例如T [] 使用新和删除来初始化并销毁它。
我已经实现了缓冲类,并在具有预期输出的整数上进行了测试。但它不适用于std::string
。问题是,当我弹出缓冲区时,我通过将其设置为零来清除元素,并且编译器抱怨这样做是不明确的。因此,我需要一种通用的方法来清除元素,我认为std::array
可能支持此功能,但我在文档中找不到它。
是否有通用的方法来清除std :: array或基本数组中的元素,或者std :: allocator是唯一的选项吗?或者,如果我完全走错方向,我应该如何实现pop方法重置第一个元素并将前索引增加到下一个元素?
提前致谢!
如果有帮助,以下是我的相关代码:
template<class T> T CircularBuffer<T>::pop_front()
{
if (_size == 0)
return 0;
T value = buffer[_front];
buffer[_front] = 0;
if (--_size == 0)
{
_front = -1;
_back = -1;
}
else
{
_front = (_front + 1) % _capacity;
}
return value;
}
答案 0 :(得分:2)
在circular buffer中你并没有真正从内存中删除元素,否则Jagannath指出std::deque是你的选择。你更喜欢&#34;重置&#34;已经弹出的元素。
buffer[_front] = 0;
表示&#34;将0
分配给T
&#34;。 T = std::string
有两种方法可以解释这种模糊性。有点简化它们看起来像这样:
std::string std::string::operator=(char c);
std::string std::string::operator=(const char *cPtr);
我想你不想要任何这个,所以我的选择是(如T.C.所写):
buffer[_front] = T();
此外(并且出于非常类似的原因)
if (_size == 0)
return 0;
也是一个问题,因为它会崩溃,请注意:
std::string a = circularBuffer.pop_front(); // crashes on empty buffer
你可以 return T()
,但更干净的方式肯定会抛出std::out_of_range
例外。
答案 1 :(得分:1)
您可以这样做的一种方法是将内存视为原始内存,并使用放置新的和手动析构函数调用。
看起来像这样:
void push(const T& val)
{
new ( data + sizeof(T)*idx++ ) T { val };
}
void pop()
{
( (T*) (data + sizeof(T)*--idx) ) -> ~T();
}