I'm learning c++ iterators.
While poking around with various excercises and algorithms, I was astonished by finding out that .begin() and .end() change address after adding elements. This breaks things like boundary checking of an iterator stored before a push_back().
I'm even more baffled that the different addresses still apparently resolve to the correct payload.
I replicated a basic example that just does basic allocation and show how the addresses change:
#include <cstdio>
#include <vector>
int main()
{
printf("std vector push back changes begin and end\n");
auto show_vector_stats = []( std::vector<int> &iras32_source )
{
printf("Begin: %p | End: %p | Diff: %d | Size: %d\n", iras32_source.begin(), iras32_source.end(), iras32_source.end() -iras32_source.begin(), iras32_source.size() );
};
//Create a vector
std::vector<int> as32_my_array;
show_vector_stats( as32_my_array );
//add first element
as32_my_array.push_back( 999 );
show_vector_stats( as32_my_array );
//Store iterator and index of first element
int index_first_element = 0;
std::vector<int>::iterator iterator_first_element = as32_my_array.begin();
printf("Index from Iterator: %d\n", iterator_first_element -as32_my_array.begin());
//Store more elements
as32_my_array.push_back( 2 );
show_vector_stats( as32_my_array );
for (int s32_cnt = 0; s32_cnt < 10; s32_cnt++)
{
as32_my_array.push_back( 101 +s32_cnt);
}
show_vector_stats( as32_my_array );
//Access by previously stored index and iterators
printf("Access by index: %d | Address of element: %p\n", as32_my_array[index_first_element], &as32_my_array[index_first_element] );
printf("Access by iterator: %d | Address of element: %p\n", *iterator_first_element, iterator_first_element );
printf("Index from Iterator: %d\n", iterator_first_element -as32_my_array.begin());
return 0;
}
OUTPUT:
std vector push back changes begin and end
Begin: 00000000 | End: 00000000 | Diff: 0 | Size: 0
Begin: 00fc1a80 | End: 00fc1a84 | Diff: 1 | Size: 1
Index from Iterator: 0
Begin: 00fc1b70 | End: 00fc1b78 | Diff: 2 | Size: 2
Begin: 00fcac28 | End: 00fcac58 | Diff: 12 | Size: 12
Access by index: 999 | Address of element: 00fcac28
Access by iterator: 999 | Address of element: 00fc1a80
Index from Iterator: -9322
Process returned 0 (0x0) execution time : 0.050 s
Press any key to continue.
I was under the impression that modern iterators were a drop-in superior and more modern version of indexes. But some things like checking a previous iterator against a more recent .begin() will return a wrong index, like in the example above, begin()-iterator returns 0 the first time, and returns -9322 after some more elements are added...
The difference between .end() and .begin() shows the correct vector size. Likewise, in a loop without changes, the difference iterator-begin() will show the correct index.
The documentations doesn't mention that begin() will return a different address potentially with every push_back(). Only that it's empty at the beginning, like the example above shows. https://cplusplus.com/reference/vector/vector/begin/
Are iterators ONLY supposed to be used for read only loops? Am I missing something, like I'm I resolving addresses wrong?
Aucun commentaire:
Enregistrer un commentaire