3

I'd like to fill a vector with a (known at runtime) quantity of data, but the elements arrive in (index, value) pairs rather than in the original order. These indices are guaranteed to be unique (each index from 0 to n-1 appears exactly once) so I'd like to store them as follows:

vector<Foo> myVector;
myVector.reserve(n); //total size of data is known
myVector[i_0] = v_0; //data v_0 goes at index i_0 (not necessarily 0)
...
myVector[i_n_minus_1] = v_n_minus_1;

This seems to work fine for the most part; at the end of the code, all n elements are in their proper places in the vector. However, some of the vector functions don't quite work as intended:

...
cout << myVector.size(); //prints 0, not n!

It's important to me that functions like size() still work--I may want to check for example, if all the elements were actually inserted successfully by checking if size() == n. Am I initializing the vector wrong, and if so, how should I approach this otherwise?

donnyton
  • 5,874
  • 9
  • 42
  • 60
  • 3
    that's because reserve doesn't resize vector. you want to use `vector.resize` instead – Anycorn Apr 04 '14 at 00:07
  • Is `Foo` default-constructible? The three solutions so far all assume it is. Otherwise it might be necessary to store the input values, and then construct all the Foo's in one go. – MSalters Apr 04 '14 at 08:50

2 Answers2

5

myVector.reserve(n) just tells the vector to allocate enough storage for n elements, so that when you push_back new elements into the vector, the vector won't have to continually reallocate more storage -- it may have to do this more than once, because it doesn't know in advance how many elements you will insert. In other words you're helping out the vector implementation by telling it something it wouldn't otherwise know, and allowing it to be more efficient.

But reserve doesn't actually make the vector be n long. The vector is empty, and in fact statements like myVector[0] = something are illegal, because the vector is of size 0: on my implementation I get an assertion failure, "vector subscript out of range". This is on Visual C++ 2012, but I think that gcc is similar.

To create a vector of the required length simply do

vector<Foo> myVector(n);

and forget about the reserve.

(As noted in the comment you an also call resize to set the vector size, but in your case it's simpler to pass the size as the constructor parameter.)

TooTone
  • 7,129
  • 5
  • 34
  • 60
  • I don't think GCC does the same checks, because G++ doesn't really do `_DEBUG` builds like VC++ does. This is one area where VC++ beats out G++ in my opinion. – Mooing Duck Apr 04 '14 at 00:30
  • 1
    @MooingDuck thankyou. I'd thought that gcc picked up on the [SGI/stlport](http://www.stlport.org/doc/sgi_stl.html) implementation. I used this for years on Windows until Microsoft finally got its act together. The SGI stl does/did provide checking, which you have to turn on. [Here is an answer about enabling checking in gcc](http://stackoverflow.com/questions/5594686/gcc-stl-bound-checking). But as you say, you'd actually have to manually configure your makefiles or whatever to have separate DEBUG and RELEASE modes (I do remember having this way back in the 90s when I worked on *nix devmnt). – TooTone Apr 04 '14 at 00:46
  • gcc _isn't_ similar. Range checking isn't enabled by default (see http://stackoverflow.com/a/5594728) – TooTone Jul 20 '16 at 15:40
4

You need to call myVector.resize(n) to set (change) the size of the vector. calling reserve doesn't actually resize the vector, it just makes it so you can later resize without reallocating memory. Writing past the end of the vector (as you are doing here -- the vector size is still 0 when you write to it) is undefined behavior.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226