Что происходит с элементом при использовании remove_if?
Я пытаюсь понять как remove_if
работает (<<
перегружен) и для этого я хочу удалить все строки, которые начинаются с 'C':
vector<string> langs = { "Python", "C++", "C", "Java", "C#" };
cout << "Initial vector: " << langs << " | Size = " << langs.size() << endl;
Выход: Initial vector: Python C++ C Java C# | Size = 5
Тогда я пишу:
auto it = remove_if(begin(langs), end(langs), [](const string& s)
{ return s[0]== 'C';});
cout << "After remove_if: " << langs << " | Size = " << langs.size() << endl;
Выход 2: After remove_if: Python Java C C# | Size = 5
Что я понимаю: элементы, которые должны остаться, удаляются в начале и *it
теперь равняется "C"
Вопрос: что происходит с "C++"
? Если "Java"
заменил, почему
for(auto& _it = it; _it != end(langs); _it++)
cout << *_it << " ";
дает вывод 3: C C#
и не "C", "Java", "C#"
?
1 ответ
remove_if
в основном вариация copy_if
где место назначения перезаписывает источник, а смысл предиката меняется на противоположный, наряду с оптимизацией, что он фактически не копирует ведущие элементы, если они не перемещаются. Он также использует ходы вместо копий, если это уместно.
Итак все remove_if
на самом деле это двигаться вниз (вперед) элементы, для которых предикат является ложным. Это не касается тех "оставшихся" элементов, поэтому они все еще будут там, и вам нужно позвонить erase
с возвращаемым значением remove_if
если хочешь от них избавиться.