Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you pop_back a vector and still use the iterator to the last element?

I wonder what happens if I have an iterator on the last element of the vector and do pop_back.

std::set<int> s;
s.insert(5);

std::vector<int> v = {1, 2, 3, 4, 5};

for (auto it = v.begin(); it != v.end();) {
    if (s.count(*it)) {
        std::swap(*it, v.back());
        v.pop_back();
    } else {
        ++it;
    }
}

Code above works properly (v is {1, 2, 3, 4} after that block) at least with clang, but is it correct to check if it == v.end() if it is invalidated?

like image 552
fas Avatar asked Aug 23 '19 15:08

fas


1 Answers

Your instincts are good; vector::pop_back invalidates iterators and references to the last element. If it is such an iterator, then it will be invalidated, and thus cannot be compared with v.end().

It would be much better to fix this by using algorithms and the erase-remove idiom:

auto last_it = std::remove_if(v.begin(), v.end(), [&](const auto &val) {return s.count(val) != 0;});
v.erase(last_it, v.end());
like image 116
Nicol Bolas Avatar answered Oct 17 '22 07:10

Nicol Bolas