Regarding the answer provided here: How to call erase with a reverse iterator
The following results in a segmentation fault (upon ++it
) when compiled in g++ 4.8.4 with -std=c++11. Am I misunderstanding the answer?
std::map<int,int> testmap;
testmap[0] = 1;
for(auto it=testmap.rbegin(); it!=testmap.rend(); ++it) {
testmap.erase( std::next(it).base() );
}
C++ Iterators Reverse Iterators A reverse iterator is made from a bidirectional, or random access iterator which it keeps as a member which can be accessed through base() . To iterate backwards use rbegin() and rend() as the iterators for the end of the collection, and the start of the collection respectively.
Approach: To traverse a Set in reverse order, a reverse_iterator can be declared on it and it can be used to traverse the set from the last element to the first element with the help of rbegin() and rend() functions. Get the set.
So, to iterate over a vector in reverse direction, we can use the reverse_iterator to iterate from end to start. vector provides two functions which returns a reverse_iterator i.e. vector::rend() –> Returns a reverse iterator that points to the virtual element before the start of vector.
erase
invalidates iterator, you have to reconstruct it from return of erase:
it = std::map<int,int>::reverse_iterator(testmap.erase( std::next(it).base() ));
or (c++11)
it = decltype(it){testmap.erase( std::next(it).base() )};
Demo.
For completeness, here is what the corrected loop from the original question looks like (notice that the iterator increment has been removed from the for(...)
:
for (auto rit = testmap.rbegin(); rit != testmap.rend(); /* empty */) {
if (WE_WANT_TO_ERASE(rit)) {
rit = decltype(rit){ testmap.erase(std::next(rit).base()) };
} else {
++rit;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With