矢量Resize vs Reserve嵌套向量

时间:2013-02-24 01:49:13

标签: c++ vector resize

我正在尝试使用其他项目的代码,他们有这种形式的结构:

struct data{
   std::vector<sparse_array> cols,rows;
}

struct sparse_array {
   std::vector<unsigned int> idxs;
   std::vector<double> values;

   void add(unsigned int idx, double value) {
       idxs.push_back(idx);
       values.push_back(value);
   }
}

对于我的代码,我尝试使用以下行:

data prob;
prob.cols.reserve(num_cols);
prob.rows.reserve(num_rows);

// Some loop that calls
prob.cols[i].add(idx, value);
prob.rows[i].add(idx, value);

当我将值prob.rows[i].value[j]输出到文件时,我得到全零。但是当我使用resize代替reserve时,我会得到我读到的实际值。有人可以给我一个解释吗?

2 个答案:

答案 0 :(得分:3)

函数reserve()只是分配一个连续的内存区域,其大小足以保存您指定的项目数,并将向量的旧内容移动到此新块中,这样可确保不再对向量的存储重新分配在插入时完成,只要不超过指定的容量即可。此函数用于减少重新分配的数量(这也会使迭代器无效),但不会在向量的末尾插入任何新项

从C ++ 11标准,第23.3.6.3/1节关于reserve()

  

一个指令,用于通知向量计划的大小更改,以便它可以管理存储   相应的分配。在reserve()之后,如果重新分配发生,capacity()大于或等于保留的参数;并且等于capacity()的先前值。当且仅当当前容量小于reserve()的参数时,此时才会重新分配。如果除了非CopyInsertable类型的移动构造函数之外抛出异常,则没有效果。

请注意,通过执行prob.cols[i].push_back(idx, value);,您可能会获得未定义的行为,因为i可能是一个越界索引。

另一方面,函数resize() 在向量的末尾插入项目,以便向量的最终大小将是您指定的大小(这意味着它可以如果指定的尺寸小于当前尺寸,则甚至擦除元素。如果没有为resize()的调用指定第二个参数,则新插入的项将进行值初始化。否则,它们将从您提供的值进行复制初始化。

来自C ++ 11标准,第23.3.6.3/9段关于resize()

  

如果sz <= size(),相当于erase(begin() + sz, end());。如果size() < sz,请附加   sz - size()将值初始化的元素添加到序列中。

总而言之,在调用resize()后访问您的向量得出预期结果的原因是项目实际上被添加到向量。另一方面,由于对reserve()的调用未添加任何项目,因此对非现有元素的后续访问将为您提供未定义的行为

答案 1 :(得分:0)

如果向量为空,则std::vector::resize(n)通过在末尾插入n个新元素来扩展此向量的内容。 std::vector::reserve(n)仅重新分配向量用于存储其元素的内存块,以便它足以容纳n个元素。

然后当您致电prob.cols[i]时,您正试图访问索引i处的元素。如果您之前使用过reserve,则会导致访问尚未存在元素的内存,从而产生未定义的行为

所以在这种情况下只需使用resize:)