Vector Resize vs Reserve for nested vectors

Vector Resize vs Reserve for nested vectors

本文关键字:nested vectors for Reserve Resize vs Vector      更新时间:2023-10-16

我正在尝试使用另一个项目的代码,它们的结构形式如下:

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

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

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

一种指令,用于通知矢量计划的大小更改,以便它可以管理存储分配。在reserve()之后,如果发生重新分配,则capacity()大于或等于保留的自变量;否则等于CCD_ 8的先前值。当且仅当当前容量小于reserve()的自变量时,此时才发生重新分配。如果不是由非CopyInsertable类型的move构造函数引发异常,则不会产生任何影响。

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

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

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

如果是sz <= size(),则相当于erase(begin() + sz, end());。如果size() < sz,则附加sz - size()值将元素初始化为序列。

综上所述,调用resize()后访问向量会得到预期结果的原因是项实际上正在添加到向量中。另一方面,由于对reserve()的调用不会添加任何项,因此后续对不存在元素的访问将导致未定义的行为

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

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

因此,在这种情况下只需使用resize:)