penelope
penelope

Reputation: 8428

Reallocation in std::vector after std::vector.reserve()

I have a snippet of code where I first put some values in to a std::vector and then give an address of each of them to one of the objects that will be using them, like this:

std::vector < useSomeObject > uso;

// uso is filled

std::vector < someObject > obj;

for (int i=0; i < numberOfDesiredObjects; ++i){
    obj.push_back(someObject());
    obj.back().fillWithData();
}
for (int i=0; i < numberOfDesiredObjects; ++i){
    uso[i].setSomeObject(&obj[i]);
}

// use objects via uso vector
// deallocate everything

Now, since I'm sometimes a little bit of a style freak, I think this is ugly and would like to use only 1 for loop, kind of like this:

for (int i=0; i < numberOfDesiredObjects; ++i){
    obj.push_back(someObject());
    obj.back().fillWithData();
    uso[i].setSomeObject(&obj.back());
}

Of course, I can not do that because reallocation happens occasionally, and all the pointers I set became invalid.

So, my question is: I know that std::vector.reserve() is the way to go if you know how much you will need and want to allocate the memory in advance. If I make sure that I am trying to allocate enough memory in advance with reserve(), does that guarantee that my pointers will stay valid?

Thank you.


Sidenote. This is a similar question, but there is not an answer to what I would like to know. Just to prevent it from popping up as a first comment to this question.

Upvotes: 1

Views: 947

Answers (2)

James Kanze
James Kanze

Reputation: 154047

This is, in fact, one of the principal reasons for using reserve. You are guaranteed that appending to the end of an std::vector will not invalidate iterators, references or pointers to elements in the vector as long as the new size of the vector does not exceed the old capacity.

Upvotes: 5

Alok Save
Alok Save

Reputation: 206646

If I make sure that I am trying to allocate enough memory in advance with reserve(), does that guarantee that my pointers will stay valid?

Yes, it guarantees your pointers will stay valid unless:

  • The size increases beyond the current capacity or
  • Unless, you erase any elements, which you don't.

The iterator Invalidation rules for an vector are specified in 23.2.4.3/1 & 23.2.4.3/3 as:

All iterators and references before the point of insertion are unaffected, unless the new container size is greater than the previous capacity (in which case all iterators and references are invalidated)

Every iterator and reference after the point of erase is invalidated.

Upvotes: 4

Related Questions