【问题标题】:What happens to the element when remove_if is used?使用 remove_if 时元素会发生什么?
【发布时间】:2018-02-24 07:26:42
【问题描述】:

我正在尝试了解 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#"?

【问题讨论】:

  • 我想起了一部古老的呆伯特卡通片。你有电话簿吗?得到一个。把它放在你的椅子上,然后站在上面。大喊一声,“这里的任何人都可以阅读文档吗?” cplusplus.com/reference/algorithm/remove_if :-)
  • 再读一遍。它准确解释了“删除”对象会发生什么,这取决于编译器是 C++98 还是 C++11 及更高版本。都在那里。
  • 它moves“下一个”项目,到有要删除的地方的地方,所以在你的情况下,它把“C,Java,C#”移动到“C++”的地方”,然后将“Java,C#”移动到“C++”的位置,所以有效的是“Python Java”,但你的结果是由于向量仍然有一些旧值(无效)
  • 永远记住remove和remove_if不要从容器中删除任何东西。他们只是重新排列它,以便可以使用erase 将元素从容器的末端删除(删除它们)。

标签: c++ erase-remove-idiom


【解决方案1】:

remove_if 基本上是copy_if 的变体,其中目标覆盖源,谓词的意义是相反的,以及一个优化,如果它们不移动,它实际上不会复制前导元素.如果相关的话,它还使用移动而不是复制。

所以remove_if 真正所做的只是将谓词为假的元素向下(朝向前面)移动。它不会触及那些“剩余”元素,所以它们仍然存在,如果你想摆脱它们,你需要调用erase,返回值为remove_if。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-06
    • 2012-04-22
    • 2010-10-28
    • 2011-08-25
    • 2017-02-07
    • 2021-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多