0

I'm trying to understand how remove_if works (the << is overloaded) and for that I want to remove_if all the strings which begin with 'C':

vector<string> langs = { "Python", "C++", "C", "Java", "C#" };
cout << "Initial vector: " << langs << " | Size = " << langs.size() << endl;

Output: Initial vector: Python C++ C Java C# | Size = 5

Then I write:

auto it = remove_if(begin(langs), end(langs), [](const string& s) 
                                              { return s[0]== 'C';});
cout << "After remove_if: " << langs << " | Size = " << langs.size() << endl;

Output 2: After remove_if: Python Java C C# | Size = 5

What I understand: elements that should remain are removed to the beginning and the *it now equals "C"

Question: What happens to "C++"? If "Java" replaced it, why

for(auto& _it = it; _it != end(langs); _it++)
    cout << *_it << " ";

gives Output 3: C C# and not "C", "Java", "C#"?

alekscooper
  • 795
  • 1
  • 7
  • 19
  • Post a [MCVE] along with a description of the intended output and the actual output. – Jive Dadson Feb 24 '18 at 07:28
  • Are you asking how elements get removed from a vector? It’s by shifting every element after them over. – Ry- Feb 24 '18 at 07:28
  • 4
    [Using `erase`-`remove_if` idiom](https://stackoverflow.com/q/39019806/335858) – Sergey Kalinichenko Feb 24 '18 at 07:30
  • 1
    I am reminded of an old Dilbert cartoon. Do you have a telephone book? Get one. Put it in your chair and stand on it. Yell out, "Can anyone here read documentation?" http://www.cplusplus.com/reference/algorithm/remove_if/ :-) – Jive Dadson Feb 24 '18 at 07:31
  • @JiveDadson What makes you think I didn't read it? Actually I did write the I-understand part to show that I did. My question was what happens to the element physically and why the size remains the same even though we can't see the element in the output. – alekscooper Feb 24 '18 at 07:36
  • 1
    Read it again. It explains exactly what happens to the "removed" object, which depends on whether the compiler is C++98 or C++11 and later. It's all there. – Jive Dadson Feb 24 '18 at 07:40
  • 1
    It [moves](http://en.cppreference.com/w/cpp/language/move_assignment) the "next" item, to the place which has the place to be removed, so in your case, it moved "C, Java, C#", to the place of "C++", then moved "Java, C#" to place of "C++", so the valid is "Python Java", but your result are due to that the vector still have some old values (invalid) – user9335240 Feb 24 '18 at 07:47
  • 2
    Always remember that `remove` and `remove_if` do not remove anything from the container. They just rearrange it so that `erase` can be used to zap the elements off of the end of the container (which removes them). – Jesper Juhl Feb 24 '18 at 08:25
  • 1
    It is all explained in [this reference](http://en.cppreference.com/w/cpp/algorithm/remove). – juanchopanza Feb 24 '18 at 09:06
  • why they named `remove` and `remove_if` methods that don't remove anything but actually move objects around is the real mistery to me. Anyone can give a reference about such strange choice? – Gian Paolo Feb 24 '18 at 17:56
  • Possible duplicate of [std::remove\_if not working properly](https://stackoverflow.com/questions/22729906/stdremove-if-not-working-properly) – xskxzr Feb 25 '18 at 11:33

1 Answers1

0

remove_if is basically a variation of copy_if where the destination overwrites the source, and the sense of the predicate is reversed, along with an optimization that it doesn't actually copy the leading elements if they're not moving. It also uses moves instead of copies, if that is relevant.

So all remove_if really does is move down (towards the front) elements for which the predicate is false. It doesn't touch those 'left over' elements, so they'll still be there and you need to call erase with the return value of remove_if if you want to get rid of them.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226