我正在尝试使用其他项目的代码,他们有这种形式的结构:
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
时,我会得到我读到的实际值。有人可以给我一个解释吗?
答案 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
:)