C ++:为向量中的非连续索引赋值?

时间:2009-05-30 15:44:37

标签: c++ stl vector

如果我想声明未知大小的向量,则按顺序将值分配给索引5,索引10,索引1,索引100。它是否可以在矢量中轻松实现?

似乎没有简单的方法。因为如果我初始化一个没有大小的向量,那么我不能通过执行resize()或五个push_back()来首先为它分配内存来访问索引5。但调整大小会清除向量中先前存储的值。我可以通过给它一个大小开始构造向量,但我不知道向量应该有多大。

那么我怎么能不必声明固定大小,仍然可以访问向量中的非连续索引?

(我怀疑这个任务的数组会更容易。)

4 个答案:

答案 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)向量。这一切都归结为您是想要稀疏表示还是自动调整大小;希望这个答案涵盖两者。