是否有一个类似于数组的类,它是一个类似POD的类型,带有一个数组,但在容器中提供了可变数量的项目。也就是说,我想说数组最多有10个项目,但在任何给定时刻可能包含0到10个项目。
遗憾的是,{p>boost::array
将size()
修复为常量N
,因此无法替代向量。特别是我希望结构的读者不要知道它是静态数组,他们可以像任何其他容器一样使用begin()
和end()
。
显然push_back()
如果超出容量范围就必须通过异常。
boost
中的某些内容将是首选。
注意:必须是类似POD的数据类型。为清楚起见,整个类似数组的对象,包括内容(它们本身是类似POD的类型)必须是类似POD的。这是出于序列化/复制的原因(以及与序列化/复制相关的性能)。
像POD一样我的意思是:
对于那些说无法工作或不可能的人。这没有什么巧妙的。 boost::array
是类似POD的类型。它只需要为当前大小添加一个额外的字段,使其成为我想要的。我正在寻找已经存在的实现(因此经过适当的测试/维护)。
答案 0 :(得分:2)
问题是(可能)初始化。你如何初始化 大小,如果是POD?你如何执行不变量 size()< = max_size?
从技术上讲,定义一些东西很容易,但是否是 另一个问题是有用的还是安全的。你为什么不 只需使用boost :: array,并保持当前大小为 一个单独的变量?
- 詹姆斯坎泽
答案 1 :(得分:1)
你说“它必须是POD数据类型”。您的收藏不需要是POD吗?
如果数据类型是POD,则std::vector
提供您需要的功能,许多实现将优化数据为POD的复制/移动语义。
为什么需要替换矢量?
直接回答这个问题:我怀疑在增强中存在这样一个类,因为矢量(保持大小)已经达到了目的,因此他们认为没有真正需要它。 boost::array
没有不同大小和容量的概念。
如果超过你设置的容量,你可以轻松地在vector或boost :: array周围编写自己的包装类。
现在,如果你要实现它,最可能的方法是包含向量或boost数组或常规数组的类,然后实现所有函数。我会说这是直观的,但可能有一个更聪明的解决方案来重载分配器,而不是内部持有一个boost ::数组并使用它来制作矢量的“分配”。如果你的分配器用完了容量(因为它的内部数组已满),你就抛出(应该是bad_alloc)。然后,用户只需将该类用作向量,并可以调用其所有函数,但如果他们尝试将向量增加到高于其大小,则会抛出。
由于向量的性质,您的分配器不能用作释放某些对象的堆。您只需维护一个连续的缓冲区。
关于POD或接近POD的问题,向量中的实际数据保证是一个连续的缓冲区,并且在内部你的分配器使用boost :: array,因此它将是连续的。如果你想要序列化的东西,那么boost :: serialize已经可以正确地使用向量。
整个集合,容器和 内容,必须是单个块 固定大小的记忆:确定为 编译时
您的分配器可能如下所示:
typename< typename T, size_t SIZE >
class Allocator
{
struct Data
{
size_t num_used;
T[SIZE] data;
} d;
public:
// implement allocator's methods
};
实施these
答案 2 :(得分:1)
我知道的更接近的事情是llvm::SmallVector<T,N>
但是它稍微复杂一点,因为它在大小超过N
时使用动态分配的存储(它还会复制现有项目,因为存储是有保证的是连续的。)
我认为实现这样的容器并不困难,特别是使用boost::array
作为后端。一个简单的包装器来保持尺寸并移动物品(例如从vector
的代码中获取灵感)就足够了。
答案 3 :(得分:0)
POD代表普通旧数据。 “C ++中的普通旧数据结构是一个聚合类,它只包含PODS作为成员,没有用户定义的析构函数,没有用户定义的复制赋值运算符,也没有指向成员类型的非静态成员。”基本上,根据定义,任何可以在运行时调整大小的东西都不能是POD。
答案 4 :(得分:0)
另一个替代方案(如果你不能被RYO打扰)就是对数组使用boost::optional<T>
,例如:
boost::array<boost::optional<int>, 10>
上述优点是您可以测试每个条目以查看它是否已设置,而不是使用某些值未初始化的状态。这应该仍然允许对象的直接memcopy(无论是堆栈还是动态分配)。
答案 5 :(得分:0)
我需要类似的东西,动机是性能,因为缓存局部性明显优于动态分配的矢量。
我为我创建了非常简单的自定义类。
#pragma once
#include <boost/array.hpp>
template<class T, class IndexType, IndexType MaximumSize>
class StaticVector : public boost::array<T, MaximumSize>
{
IndexType count;
public:
StaticVector() : count(0) {}
inline void add(const T& value)
{
if (this->full())
throw std::runtime_error("Can't add (size = %d)\n", MaximumSize);
(*this)[this->count] = value;
this->count++;
}
inline void addDirty()
{
if (this->full())
throw std::runtime_error("Can't add, container full.");
this->count++;
}
inline void remove(IndexType index)
{
if (this->count > 1)
(*this)[index] = (*this)[count - 1];
this->count--;
}
inline void clear() { this->count = 0; }
inline IndexType size() const { return this->count; }
inline bool empty() const { return this->count == 0; }
inline bool full() const { return this->count == MaximumSize; }
inline const T& back() const { return (*this)[this->count - 1]; }
inline T& back() { return (*this)[this->count - 1]; }
inline typename boost::array<T, MaximumSize>::iterator end() { return this->elems + count; }
inline typename boost::array<T, MaximumSize>::const_iterator end() const { return this->elems + count; }
inline typename boost::array<T, MaximumSize>::const_iterator cend() const { return this->elems + count; }
};