1

Let's say I have this code:

std::vector<Object*> objects;
std::vector<Object*>::iterator iter;
for (iter = objects.begin(); iter != objects.end(); iter++) {
    if (condition)
        objects.push_back(new Object());
}

However, when push_back occurs, iter becomes undereferenceable. Without resetting iter, how do I keep it dereferenceable? If I have to reset it, is there an easy way to do it so iter goes back to where it was before?

Sk8torchic
  • 11
  • 1
  • As a side note, theres a possible logical bug in this idea in that if you 'add' objects to the end while you iterate, its possible that you could get into an infinite loop as more and more objects are added and iteration never terminates (theres always another object to iterate to!) – MerickOWA Dec 07 '10 at 20:44

6 Answers6

5

I would recommend that you simply access it by index. This completely eliminates the issue.

Dark Falcon
  • 43,592
  • 5
  • 83
  • 98
1

If you absolutely must use iterators for this:

std::vector<Object*> objects;
std::vector<Object*> newObjects;
std::vector<Object*>::iterator iter;
for (iter = objects.begin(); iter != objects.end(); ++iter)
{
    if (condition)
    {
        newObjects.push_back(new Object());
    }
}

std::copy(newObjects.begin(), newObjects.end(), back_inserter<vector<Object*> >(objects));
Zac Howland
  • 15,777
  • 1
  • 26
  • 42
0

You will have to result to an old fashioned for loop with numerical indices. Either that, or reserve() the vector before the loop runs to guarantee it won't resize.

Also, raw pointers? Srsly.

Puppy
  • 144,682
  • 38
  • 256
  • 465
0

The iterator only becomes invalidated if the vector has to reallocate more memory.

To prevent the reallocation of memory pre-allocate all the memory you need with reserve() (assuming you know this size when you allocate the vector).

The easier solution keep an indirect reference to the member (an index in the array).

Martin York
  • 257,169
  • 86
  • 333
  • 562
0

§23.1/11:

Unless otherwise specified (either explicitly or by defining a function in terms of other functions), invoking a container member function or passing a container as an argument to a library function shall not invalidate iterators to, or change the values of, objects within that container.

However, it is not explicitly specified, that std::vector::push_back invalidates any iterators.

Oswald
  • 31,254
  • 3
  • 43
  • 68
  • Some tests I've done confirm that the push_back can indeed invalidate an iterator. – Oswald Dec 10 '10 at 17:05
  • The reason is probably, that a vector is a sequence and for a sequence s, s.push_back(x) is defined as s.insert(s.end(), x) and std::vector::insert is allowed to invalidate iterators. – Oswald Dec 10 '10 at 17:29
0

As most of the other answers already say, you're probably better accessing the vector by index in this case.

However, for completeness: std::list iterators don't have this "problem". So using list instead of vector is a possible solution.

Éric Malenfant
  • 13,938
  • 1
  • 40
  • 42