1

I'm trying to use another project's code and they have structs of this form:

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);
   }
}

For my code, I tried using the following lines:

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);

And when I output the values, prob.rows[i].value[j] to a file I get all zeros. But when I use resize instead of reserve I get the actual value that I read in. Can someone give me an explanation about this?

Hank
  • 3,367
  • 10
  • 48
  • 86
  • See similar questions: [Choice between vector::resize() and vector::reserve()](http://stackoverflow.com/q/7397768/1168156) and [std::vector::resize() vs. std::vector::reserve()](http://stackoverflow.com/q/13029299/1168156) – LihO Feb 24 '13 at 02:10

2 Answers2

3

Function reserve() simply allocates a contiguous region of memory big enough to hold the number of items you specify and moves the vector's old content into this new block, which makes sure no more reallocations for the vectors' storage will be done upon insertions as long as the specified capacity is not exceeded. This function is used to reduce the number of reallocations (which also invalidate iterators), but does not insert any new items at the end of your vector.

From the C++11 Standard, Paragraph 23.3.6.3/1 about reserve():

A directive that informs a vector of a planned change in size, so that it can manage the storage allocation accordingly. After reserve(), capacity() is greater or equal to the argument of reserve if reallocation happens; and equal to the previous value of capacity() otherwise. Reallocation happens at this point if and only if the current capacity is less than the argument of reserve(). If an exception is thrown other than by the move constructor of a non-CopyInsertable type, there are no effects.

Notice that by doing prob.cols[i].push_back(idx, value); you are likely to get undefined behavior, since i is probably an out-of-bounds index.

On the other hand, function resize() does insert items at the end of your vector, so that the final size of the vector will be the one you specified (this means it can even erase elements, if you specify a size smaller than the current one). If you specify no second argument to a call to resize(), the newly inserted items will be value-initialized. Otherwise, they will be copy-initialized from the value you provide.

From the C++11 Standard, Paragraph 23.3.6.3/9 about resize():

If sz <= size(), equivalent to erase(begin() + sz, end());. If size() < sz, appends sz - size() value-initialized elements to the sequence.

So to sum it up, the reason why accessing your vector after invoking resize() gives the expected result is that items are actually being added to the vector. On the other hand, since the call to reserve() does not add any item, subsequent accesses to non-existing elements will give you undefined behavior.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
0

If the vector is empty, then std::vector::resize(n) expands the content of this vector by inserting n new elements at the end. std::vector::reserve(n) only reallocates the memory block that your vector uses for storing its elements so that it's big enough to hold n elements.

Then when you call prob.cols[i], you are trying to access the element at index i. In case you used reserve before, this results in accessing the memory where no element resides yet, which produces the undefined behavior.

So just use resize in this case :)

LihO
  • 41,190
  • 11
  • 99
  • 167