如果我想声明未知大小的向量,则按顺序将值分配给索引5,索引10,索引1,索引100。它是否可以在矢量中轻松实现?
似乎没有简单的方法。因为如果我初始化一个没有大小的向量,那么我不能通过执行resize()或五个push_back()来首先为它分配内存来访问索引5。但调整大小会清除向量中先前存储的值。我可以通过给它一个大小开始构造向量,但我不知道向量应该有多大。
那么我怎么能不必声明固定大小,仍然可以访问向量中的非连续索引?
(我怀疑这个任务的数组会更容易。)
答案 0 :(得分:13)
整数键和值之间的std :: map不是一个更简单的解决方案吗?向量将需要连续的内存分配,所以如果你只使用偶尔的索引,你将“浪费”大量的内存。
答案 1 :(得分:8)
调整大小不会清除矢量。您可以轻松地执行以下操作:
if (v.size() <= n)
v.resize(n+1);
v[n] = 42;
这将保留向量中的所有值,并添加足够的默认初始值,以便可以访问索引n
。
也就是说,如果你不需要所有索引或连续内存,你可能会考虑不同的数据结构。
答案 2 :(得分:4)
resize()
不会清除矢量中先前存储的值
见this documentation
我还会争辩说,如果这是你需要做的事情,那么vector
可能不是你的容器。你考虑过使用map
吗?
答案 3 :(得分:0)
不包含连续值集的数据结构称为稀疏或压缩数据结构。看来这就是你要找的东西。
如果是这种情况,您需要稀疏矢量。有一个在boost中实现,请参阅link text
稀疏结构通常用于节省内存。从您的问题描述中可能实际上并不关心内存使用,而是关于寻址尚不存在的元素(您需要一个自动调整大小的容器)。在这种情况下,没有外部依赖关系的简单解决方案如下:
创建一个包含向量的模板类,并将所有向量方法转发给它。如果索引超出范围,请更改operator []以调整向量的大小。
// A vector that resizes on dereference if the index is out of bounds.
template<typename T>
struct resize_vector
{
typedef typename std::vector<T>::size_type size_type;
// ... Repeat for iterator/value_type typedefs etc
size_type size() const { return m_impl.size() }
// ... Repeat for all other vector methods you want
value_type& operator[](size_type i)
{
if (i >= size())
resize(i + 1); // Resize
return m_impl[i];
}
// You may want a const overload of operator[] that throws
// instead of resizing (or make m_impl mutable, but thats ugly).
private:
std::vector<T> m_impl;
};
如其他答案所述,调整矢量大小时不会清除元素。相反,当通过调整大小添加新元素时,将调用其默认构造函数。因此,您需要知道何时使用此类operator[]
可能会返回默认的构造对象引用。因此,<T>
的默认构造函数应该将对象设置为合理的值。例如,如果您需要知道元素之前是否已赋值,则可以使用sentinel值。
使用std::map<size_t, T>
的建议也有优点作为解决方案,前提是您不介意额外的内存使用,非连续元素存储和O(logN)查找而不是O(1)向量。这一切都归结为您是想要稀疏表示还是自动调整大小;希望这个答案涵盖两者。