My understanding is the iterators of associative containers are not invalidated during insert or erase (unless the node pointed by iterator is erased). But in the below program the insert seems to invalidate the iterator. Is my understanding wrong?
typedef std::set<unsigned int> myset_t;
int main(int argc, char **argv)
{
myset_t rs;
myset_t::reverse_iterator rit;
myset_t::reverse_iterator srit;
int ii = 500;
rs.insert(10);
rs.insert(11);
rs.insert(12);
rs.insert(13);
rs.insert(14);
rs.insert(100000);
rs.insert(102000);
rs.insert(103000);
rit = rs.rbegin();
while(rit != rs.rend()) {
srit = rit;
if (*rit < 100000) {
cout << "bailing here " << *rit << endl;
return 0;
}
rit++;
cout << "Before erase " << *rit << endl;
rs.erase(*srit);
cout << "Before insert " << *rit << endl;
rs.insert(ii);
cout << "After insert " << *rit << endl;
ii++;
}
cout << "Out of loop" << endl;
}
===
The output is
Before erase 102000
Before insert 102000
After insert 14
bailing here 14
=====
The promised behavior for iterators of a standard container does not hold for reverse iterators of that container.
A reverse iterator actually stores, as a member, the normal (forward moving) iterator which comes after the element to which the reverse iterator refers when dereferenced. Then when you dereference the reverse iterator, essentially it decrements a copy of this stored normal iterator and dereferences that. So this is a problem:
Reverse iterators behave this way because there is no "before begin" iterator. If they stored the iterator to the element to which they actually refer, what would
rs.rend()
store? I'm sure there are ways around this, but I guess they required compromises which the standards committee was not willing to make. Or perhaps they never considered this problem, or didn't consider it significant enough.