Suppose I want to remove items according to some criterium. Let's say:
QMap<int, int> map;
and I want to remove all the items where value is an odd number. If I use an iterator:
for (auto it = map.begin(); it != map.end(); ++it)
    if (it.value() % 2 == 1)
        map.remove(it.key());
This code is probably wrong, since the call of
map.remove(it.key()) 
invalidates the iterator. How can I do this without reseting the iterator after each removal?
Use QMap::erase instead, which returns an iterator to the element following the one you just erased:
for (auto it = map.begin(); it != map.end();)
    if (it.value() % 2 == 1)
        it = map.erase(it);
    else
        ++it;
Another way is to use the postfix increment operator on the iterator:
for (auto it = map.begin(); it != map.end();)
    if (it.value() % 2 == 1)
        map.erase(it++);
    else
        ++it;
Yet another way (and probably less efficient) is to use the STL remove_copy_if algorithm, followed by swap:
bool valueIsOdd(int value) {return value % 2 == 1;}
QMap<int,int> b;
std::remove_copy_if(a.begin(), a.end(),
                    std::inserter(b, b.end()),
                    &valueIsOdd);
a.swap(b);
I cannot test the last example at the moment.
You would be better off using the more STL-like erase function:
Using this, you can implement your loop correctly as:
for (auto it = map.begin(); it != map.end(); /* don't increment here */) {
    if (it.value() % 2 == 1) {
        it = map.erase(it);
    } else {
        ++it;
    }
}
I think you could get the same result from map.remove((it++).key()), but that would be both slower and messier than erase.
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