1

I have put together a theory that explains a phenomenon, but I'd like someone more knowledgeable to bear me up.

In the client code, I have:

vector<bool> candidates;
fillCandidates(candidates);

In the callee, I have:

void fillCandidates(vector<bool>& candidates)
{
    // reserve space for two elements
    candidates.reserve(2);
    candidates[0] = true;
    candidates[1] = false;
    // here, candidates.size() == 0
}

When I check the size of candidates after the return of the function, it is 0! What's happening? I'm using gcc 4.6.3 called in a CMake script on a Ubuntu 12.04 64-bit (but I think all of this is actually irrelevant).

Note: I'm providing my interpretation as an answer.

Edit: The accepted answer and the comments beat me on timing, so my interpretation wouldn't add anything.

sturmer
  • 350
  • 5
  • 17
  • 1
    Either call `resize` instead of `reserve` as the answer mentions, or call `push_back` instead of `operator[]` after calling `reserve`. – Praetorian Oct 15 '13 at 16:58
  • 1
    FWIW, doing a `reserve` is more appropriate only when the count is high and is known beforehand. Calling `resize` and then overwriting elements is mostly less performant, except for PODs/built-ins. If you can use C++11, doing an `emplace_back` is apt in most cases and performant too. – legends2k Oct 15 '13 at 17:16
  • @legends2k: Could you point me to the source of your statement about the performance of `emplace_back`? It's interesting. – sturmer Oct 15 '13 at 17:20
  • @sturmer: [push_back vs emplace_back](http://stackoverflow.com/q/4303513/183120) – legends2k Oct 15 '13 at 17:22

1 Answers1

4

You should be calling resize, not reserve.

See the differences here: Choice between vector::resize() and vector::reserve()

Edit to answer comments below:

The short answer is yes, calling operator[] on a vector that is only reserved is an error, and anything could happen.

The long answer is read this article http://www.gotw.ca/gotw/074.htm

v.reserve( 2 ); v[0] = 1; v[1] = 2; Both of the above lines are flat-out errors, but they might be hard-to-find flat-out errors because they'll likely "work" after a fashion on your implementation of the standard library.

I suggest reading the whole thing. In your case I would use push_back instead of resizing manually. But I would benchmark performance if you are really concerned.

Community
  • 1
  • 1
Salgar
  • 7,687
  • 1
  • 25
  • 39
  • Thanks for the pointer. But then, as a side question, am I doing anything evil by using `operator[]` to assign the values? – sturmer Oct 15 '13 at 17:01
  • And anyway, I did not mean to assign 2 default values (which is what would have happened by using `resize()`). I really meant to reserve enough space, before assigning values. Isn't my real error trying to assign values with `operator[]`? Since in my case `size()` returns 0, using `operator[]` results in undefined behavior. – sturmer Oct 15 '13 at 17:04
  • 1
    @sturmer: if you're determined that you don't want your vector element to briefly take on a default value then you can create it with `push_back` instead of `resize()`. In the case of `bool` it's likely to be less efficient, though (not that efficiency is going to matter for two `bool`s). vector never has elements that haven't been initialized, and that's an intended feature. – Steve Jessop Oct 15 '13 at 17:09