1

我正在尝试使用另一个项目的代码,它们具有这种形式的结构:

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得到我读入的实际值时。有人可以给我一个解释吗?

4

2 回答 2

3

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

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

一个指令,通知向量计划的大小更改,以便它可以相应地管理存储分配。之后reserve()capacity()如果发生重新分配,则大于或等于reserve 的论点;并且等于之前的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()不添加任何项目,后续访问不存在的元素会给你未定义的行为

于 2013-02-24T01:54:53.117 回答
0

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

然后,当您调用时prob.cols[i],您将尝试访问 index 处的元素i。如果您以前使用reserve过,这将导致访问尚未驻留任何元素的内存,从而产生未定义的行为

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

于 2013-02-24T02:01:47.970 回答