How to use vector iterators when using vector<>::push_back()

kilgoretrout

For simplicity, I'll stick to vector<int> but I think this applies to any vector<T> object.

If I am using a vector<int>::iterator to keep track of some position in a vector of int's and then I use vector<int>::push_back(), the iterator becomes worthless. Meaning, I can't take its address with & or dereference it. The direct reason made sense once I printed the address of some of the objects in the following sense:

vector<int> my_vec(1); //my_vec[0] = 0

vector<int>::iterator it = my_vec.begin(); //it -> my_vec[0], *it = my_vec[0] = 0

cout << "&my_vec = " << &my_vec << "\n";
cout << "&my_vec[0] = " << &my_vec[0] << "\n";
cout << "&it = " << &it << "\n"; //prints address, all good
cout << "*it = " << *it << "\n"; //prints 0, all good

cout << "\n\n" << pushing back..." << "\n\n";
my_vec.push_back(1);

cout << "&my_vec = " << &my_vec << "\n"; //same as before push_back()!
cout << "&my_vec[0] = " << &my_vec[0] << "\n"; //different from before push_back()!!
cout << "&it = " << &it << "\n"; //same as before push_back()
//cannot do &it or *it

So obviously the address of it doesn't change but push_back() has moved things around in memory and now the address of the different "elements" of my_vec are changed. The fact that my_vec[i] has a new address made sense to me but then I have the following questions:

1) Why doesn't the address of my_vec change? It seems that if push_back() causes the addresses of the my_vec[i] to change, it should also change the address of the whole object. For an array, my_array is a pointer to my_array[0] so I can imagine an operation changing the addresses of each my_array[i] and updating the pointer to point to the new address of my_array[0] but the address of the pointer my_array as an object in and of itself wouldn't change. But my_vec is not a pointer in any sense to my_vec[0] so I am confused why the addresses of the my_vec[i] would change but not the object my_vec.

2) Why would any operation internal to vector<int> that changes the address of the my_vec[i] (such as push_back()) not also properly "update" any iterators? This seems like a good idea? No?

3) Given that #2 is what it is and my iterators become worthless when I call push_back(), what is the correct way to deal with this? Should I not use iterators if I need to use push_back()? If someone is going to complain about what my use-case is for using iterators and push_back(), I excluded it for brevity but it was basically implementing a stack using vector<int> and I was using an iterator to keep track of the top of the stack. Since I didn't want a fixed size to start, I tried to use push_back() to enlarge the stack when my iterator hit my_vec.end(). But I think this is a valid question in general.

Thanks very much for your help!

Mike Seymour

Why doesn't the address of my_vec change?

Because the vector object itself is still the same object at the same address. Reallocation changes the address of the dynamic array that it manages, not the vector object that manages the array.

Why would any operation internal to vector<int> that changes the address of the my_vec[i] (such as push_back()) not also properly "update" any iterators? This seems like a good idea? No?

That would have a (perhaps large) runtime cost. Either the vector would have to track all the iterators (requiring dynamic storage, memory allocation each time an iterator is created, and updating of all vectors when the vector changes) or each iterator would need a reference to the container, checked on every access, and could not be implemented as a simple pointer. C++ generally avoids runtime costs where possible - especially in cases like this, where they are nearly always unnecessary.

what is the correct way to deal with this?

There are various options. You could store an index rather than an iterator. You could use a container such as std::list with stable iterators (although that might be rather less efficient). If you can place an upper bound on the size of the array, you could reserve that amount so that reallocation won't be necessary. You could write your own container (or adapter) that automatically updates iterators. For your stack, if it is indeed a stack, you shouldn't need to track anything other than the end of the vector, so there's no need to store an iterator at all. Or you could use std::stack rather than reinventing it.

Are there any other vector<T> member functions (besides the obvious ones) that have this effect on iterators?

Iterators are invalidated by reallocation, when any operation causes the vector to grow beyond its current capacity. You can control the capacity with the reserve function.

Also, erasing elements will invalidate any iterator referring to the erased elements, or elements later in the sequence.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

How to use vector iterators when using vector<>::push_back()

From Dev

Is a std::unique_ptr moved into a std::vector when using push_back?

From Dev

Vector's push_back implementation using memcpy

From Dev

Make a vector a certain size without using push_back

From Dev

Using scanf and while loop with vector push_back

From Dev

vector push_back in STL?

From Dev

Vector and push_back() behavior

From Dev

Unable to push_back to vector

From Dev

vector push_back zero into an empty vector

From Dev

push_back a vector of vectors into a vector

From Dev

Vector of shared_ptr resulting in error: "no instance of overloaded function" when wanting to push_back vector list

From Dev

Vector of shared_ptr resulting in error: "no instance of overloaded function" when wanting to push_back vector list

From Dev

How to Iterator::chain a vector of iterators?

From Dev

how to use std::vector::emplace_back for vector<vector<int> >?

From Dev

how to use std::vector::emplace_back for vector<vector<int> >?

From Dev

When and how to use a vector of references

From Java

Insert or push_back to end of a std::vector?

From Dev

Implementatnion of std::vector::push_back in MSVC

From Dev

vector::push_back and std::move

From Dev

Why are there two overloads for vector::push_back?

From Dev

string Vector push_back failing in class

From Dev

garbage values for vector push_back

From Dev

push_back new element to vector

From Dev

Implementatnion of std::vector::push_back in MSVC

From Dev

garbage values for vector push_back

From Dev

Vector push_back incredibly slow

From Dev

Vector push_back Array of doubles

From Dev

Push_back variadic function parameters into a vector?

From Dev

c++ push_back() a struct into a vector

Related Related

  1. 1

    How to use vector iterators when using vector<>::push_back()

  2. 2

    Is a std::unique_ptr moved into a std::vector when using push_back?

  3. 3

    Vector's push_back implementation using memcpy

  4. 4

    Make a vector a certain size without using push_back

  5. 5

    Using scanf and while loop with vector push_back

  6. 6

    vector push_back in STL?

  7. 7

    Vector and push_back() behavior

  8. 8

    Unable to push_back to vector

  9. 9

    vector push_back zero into an empty vector

  10. 10

    push_back a vector of vectors into a vector

  11. 11

    Vector of shared_ptr resulting in error: "no instance of overloaded function" when wanting to push_back vector list

  12. 12

    Vector of shared_ptr resulting in error: "no instance of overloaded function" when wanting to push_back vector list

  13. 13

    How to Iterator::chain a vector of iterators?

  14. 14

    how to use std::vector::emplace_back for vector<vector<int> >?

  15. 15

    how to use std::vector::emplace_back for vector<vector<int> >?

  16. 16

    When and how to use a vector of references

  17. 17

    Insert or push_back to end of a std::vector?

  18. 18

    Implementatnion of std::vector::push_back in MSVC

  19. 19

    vector::push_back and std::move

  20. 20

    Why are there two overloads for vector::push_back?

  21. 21

    string Vector push_back failing in class

  22. 22

    garbage values for vector push_back

  23. 23

    push_back new element to vector

  24. 24

    Implementatnion of std::vector::push_back in MSVC

  25. 25

    garbage values for vector push_back

  26. 26

    Vector push_back incredibly slow

  27. 27

    Vector push_back Array of doubles

  28. 28

    Push_back variadic function parameters into a vector?

  29. 29

    c++ push_back() a struct into a vector

HotTag

Archive