4

Cannot figure out where I went wrong. As I understand, this code should return "1, 2, 3" but I get the following. I need the vector and its iterators declared globally because I am passing the vector to functions in my actual code and need to update the iterators as well in some functions. Any help is appreciated!

#include <iostream>
#include <vector>

using namespace std;

vector<float> grid;
vector<float>::iterator gridPtr;

int main()

{
  grid.push_back(1);
  grid.push_back(2);

  gridPtr = grid.begin();

  grid.push_back(3);

  cout << "gridPtr: " << *gridPtr << endl;

  gridPtr++;

  cout << "gridPtr: " << *gridPtr << endl;

  gridPtr++;

  cout << "gridPtr: " << *gridPtr << endl;
}

This returns:

gridPtr: 2.62257e-33
gridPtr: 2
gridPtr: 0
bcf
  • 2,104
  • 1
  • 24
  • 43
  • *"because I am passing the vector to functions in my actual code"* - If you are passing it to the functions, then why does it need to be global? That seems contradictory. – JBentley Mar 29 '13 at 01:38
  • JBentley - My mistake, I meant I am using them in a function and don't want to have to pass them. – bcf Mar 29 '13 at 01:54
  • [See this answer](http://stackoverflow.com/a/6438087/1227469) for an explanation of iterator invalidation. – JBentley Mar 29 '13 at 02:54
  • @David The OOP way would be to make the vector a private member of a class, with public member functions which operate on it. – JBentley Mar 29 '13 at 02:56

3 Answers3

4

push_back() may invalidate all iterators. Namely, if it has to reallocate the backing store, all existing iterators become invalidated.

If you know ahead of time how many elements you're going to push, you can use reserve() to preallocate the necessary memory, which will prevent push_back() from reallocating (and thus invalidating iterators).

Lily Ballard
  • 182,031
  • 33
  • 381
  • 347
2

From http://en.cppreference.com/w/cpp/container/vector/push_back:

If the new size() is greater than capacity(), all iterators and references are invalidated.

(Emphasis mine.)

This makes sense when you consider what's happening under the hood; a vector works by filling up a dynamically-allocated array; when it's full it needs to reallocate a bigger one, and move everything across.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
1

You may invalidate the iterator when you do a push_back, if you remove that line it should work fine. The following will work as expected:

grid.push_back(1);
grid.push_back(2);

gridPtr = grid.begin();
cout << "gridPtr: " << *gridPtr << endl;
gridPtr++;
cout << "gridPtr: " << *gridPtr << endl;

as Kevin mentioned, using reserve to allocate enough memory before-hand will also fix the issue:

grid.reserve(3) ;
grid.push_back(1);
grid.push_back(2);

gridPtr = grid.begin();

grid.push_back(3) ;
cout << "gridPtr: " << *gridPtr << endl;
gridPtr++;
cout << "gridPtr: " << *gridPtr << endl;
gridPtr++;
cout << "gridPtr: " << *gridPtr << endl;
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740