【问题标题】:Reset an element in a circular buffer重置循环缓冲区中的元素
【发布时间】:2015-07-13 09:25:51
【问题描述】:

我被要求在 C++ 中实现一个采用未指定类型的循环缓冲区。我假设泛型类型是原始类型。 (还是应该考虑非原始类型?)对于缓冲区,我使用 basic 数组,例如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;
}

【问题讨论】:

  • std::deque 应改为使用。 C++ 中没有引用类型。如果您认为class 是引用类型而struct 是值类型,那么不,事实并非如此。
  • @Jagannath 感谢您指出这一点!我已经改写为 primitive(我所说的值类型)和 non-primitive(我所说的引用类型)。
  • 所以,答案是std::deque
  • 您可以将T() 分配给元素,或者使用放置新的和显式的析构函数调用。后者更正确;前者更容易写。
  • @Jagannath 我猜 OP 希望 circular buffer 固定大小。所以没有双端队列。

标签: arrays c++11 circular-buffer stdarray


【解决方案1】:

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

它可能看起来像这样:

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

void pop()
{
    ( (T*) (data + sizeof(T)*--idx) ) -> ~T();
}

【讨论】:

  • 阅读问题我认为pop() 应该返回一个T,即即将被销毁的那个副本。
【解决方案2】:

circular buffer 中,您并没有真正从内存中删除 元素,否则正如 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);

我猜你不想要这些,所以我的选择是(如 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异常。

【讨论】:

  • 谢谢!我实际上是想问如何“重置”;我已经编辑了这个问题。那么T() 也可以应用于原始类型吗?至于异常处理,this post 说服了我,并认为我不会返回任何内容。
  • @ThomasHsieh 我明白了,如果您想节省空检查的时间,您可以考虑删除整个 if 语句。
  • @ThomasHsieh 请通过单击检查(接近投票数)将适合您需求的答案标记为“已接受”。
猜你喜欢
  • 2016-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-26
  • 2022-11-14
相关资源
最近更新 更多