See what happens if I incorrectly use remove() assuming it works in a "natural" way, and not the actual one (the dump() function is described in a previous post):
std::vector<int> v; v.reserve(10); for(int i = 0; i < 10; ++i) v.push_back(i); v[3] = v[5] = v[9] = 99; dump(v); remove(v.begin(), v.end(), 99); // !! this is not enough !! dump(v);In my environment this is the (unexpected but correct) output:
0 1 2 99 4 99 6 7 8 99 0 1 2 4 6 7 8 7 8 99As you see, remove() did its job, but we still have to get rid of the trash at the end of the container. And to do that, the best way is calling erase() on the result of remove(), that is an iterator to the "new end", and the iterator to the "current end":
// remove(v.begin(), v.end(), 99); // !! this is not enough !! v.erase(remove(v.begin(), v.end(), 99), v.end());It should be clear now why this is called "erase-remove" idiom.
So, the standard remove() algorithm and specialized container method do not actually remove anything. With an exception: the list::remove() method that does actually eliminates the element.
So, in this specific case, we use it in this way:
std::list<int> l; for(int i = 0; i < 10; ++i) l.push_back(i); dump(l); l.remove(7); // !! this works correctly !! dump(l);I often re-read the Effective C++ books by Scott Meyers. This post has been written while pondering on Item 32 of Effective STL.
No comments:
Post a Comment