1

我被要求在 C++中实现一个采用未指定类型的循环缓冲区。我假设泛型类型是原始类型。(或者它应该考虑非原始类型?)对于缓冲区,我使用一个基本数组,例如 T[]newdelete来初始化和销毁​​它。

我已经实现了缓冲区类并在具有预期输出的整数上对其进行了测试。但它不起作用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;
}
4

2 回答 2

2

循环缓冲区中,您并没有真正从内存中删除元素,否则正如 Jagannath 指出的那样,std::deque是您的选择。您更喜欢“重置”已弹出的元素。

buffer[_front] = 0;

意思是“分配0给一个T”。有两种方法可以T = std::string解释这种歧义。稍微简化一下,它们看起来像这样:

std::string std::string::operator=(char c);

std::string std::string::operator=(const char *cPtr);

我猜你不想要这些,所以我的选择是(正如 TC 所写):

buffer[_front] = T();

此外(出于非常相似的原因)

if (_size == 0)
    return 0;

这也是一个问题,因为它会崩溃,请注意:

std::string a = circularBuffer.pop_front(); // crashes on empty buffer

可以 return T()在这里,但更干净的方法肯定会抛出std::out_of_range异常。

于 2015-05-04T09:42:23.890 回答
1

您可以做到这一点的一种方法是将内存视为原始内存,并使用placement new 和手动析构函数调用。

它可能看起来像这样:

void push(const T& val)
{
    new ( data + sizeof(T)*idx++ ) T { val };
}

void pop()
{
    ( (T*) (data + sizeof(T)*--idx) ) -> ~T();
}
于 2015-05-04T06:42:05.617 回答