0

我有这个代码:

#include <algorithm>
#include <iostream>
#include <list>

using namespace std;

struct P
{
    bool operator()(const int &n) const
    {
        return n % 3 == 0;
    }
};

int main()
{
    std::list<int> l({ 5, 2, 6, 1, 13, 9, 19 });
    std::cout << l.size();
    std::remove_if(l.begin(), l.end(), P());
    std::cout << l.size() << std::endl;

    return 0;
}

打印出“77”。我预计它会打印出“75”,因为 P 结构的运算符 () 在其参数没有除以 3 的余数时返回 true。'6' 和 '9' 就是这种情况(两个元素七)。我错过了什么吗?

谢谢。

4

3 回答 3

1

引用http://www.cplusplus.com/reference/algorithm/remove_if/

该函数不能更改包含元素范围的对象的属性(即,它不能更改数组或容器的大小):删除是通过将 pred 返回 true 的元素替换为它的下一个元素来完成的没有,并通过将迭代器返回到应该被视为其新的过去元素的元素来指示缩短范围的新大小。

换句话说,它重新排列给定范围内的元素,以便所有未删除的元素都在开头,然后在未删除部分的末尾返回一个迭代器。但它不能删除任何元素,因为它对底层容器一无所知。

于 2014-03-09T22:11:37.107 回答
1

是否有可能 std::remove_if 返回结果列表?

于 2014-03-09T22:15:02.870 回答
1

remove/remove_if重新排序一个序列,它不会修改它。迭代器无法访问或了解它们来自的容器。您需要将结果传递给合适的erase容器成员:

l.erase(std::remove_if(l.begin(), l.end(), P()), l.end());

不要忘记第二个l.end(),这样你就可以得到两个迭代器重载,erase它会擦除​​整个范围。如果你忘记了它,你最终会得到一个只删除单个元素的迭代器重载。

于 2014-03-09T22:19:07.857 回答