重置循环缓冲区中的元素
Reset an element in a circular buffer
我被要求在 C++ 中实现一个采用 未指定类型 的循环缓冲区。我假设泛型类型是原始类型。 (或者它应该考虑非原始类型吗?)对于缓冲区,我使用的是 基本数组,例如T[] 用 new 和 delete 来初始化和销毁它。
我已经实现了缓冲区 class 并在具有预期输出的整数上对其进行了测试。但它不适用于 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;
}
您可以这样做的一种方法是将内存视为原始内存,并使用新的放置和手动析构函数调用。
它可能看起来像这样:
void push(const T& val)
{
new ( data + sizeof(T)*idx++ ) T { val };
}
void pop()
{
( (T*) (data + sizeof(T)*--idx) ) -> ~T();
}
在 circular buffer you do not really remove elements from memory, otherwise as Jagannath pointed out std::deque 中是您的选择。你更喜欢"reset"已经弹出的元素
buffer[_front] = 0;
表示"assign 0
to a 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
异常。
我被要求在 C++ 中实现一个采用 未指定类型 的循环缓冲区。我假设泛型类型是原始类型。 (或者它应该考虑非原始类型吗?)对于缓冲区,我使用的是 基本数组,例如T[] 用 new 和 delete 来初始化和销毁它。
我已经实现了缓冲区 class 并在具有预期输出的整数上对其进行了测试。但它不适用于 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;
}
您可以这样做的一种方法是将内存视为原始内存,并使用新的放置和手动析构函数调用。
它可能看起来像这样:
void push(const T& val)
{
new ( data + sizeof(T)*idx++ ) T { val };
}
void pop()
{
( (T*) (data + sizeof(T)*--idx) ) -> ~T();
}
在 circular buffer you do not really remove elements from memory, otherwise as Jagannath pointed out std::deque 中是您的选择。你更喜欢"reset"已经弹出的元素
buffer[_front] = 0;
表示"assign 0
to a 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
异常。