std :: remove_if并擦除不从std :: vector中删除元素

时间:2018-06-05 13:42:01

标签: c++ vector lambda

我正在练习leetcode容易出问题。我想使用lambda从vector中删除_if(这是第一次,很棒)。我得到了new_end的否定指针。

#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>   // std::greater

using namespace std;
int main()
{
    vector<int> a = { 2, 7, 11, 15 };
    int target = 9;

    auto new_end = std::remove_if(a.begin(), a.end(), [&a, target](const int x)
    {
        return std::count(a.begin(), a.end(), x) > target;  
    });
    a.erase(new_end, a.end());
    return 0;
}

没有错误,但new_end是负指针值。

enter image description here

2 个答案:

答案 0 :(得分:2)

std::remove_if(begin, end, pred)返回指向要删除的第一个元素的迭代器,如果没有匹配end的元素,则返回pred。在你的情况下,后者是正确的:

auto new_end = std::remove_if(a.begin(), a.end(),
    [&a, target](const int x) { return std::count(a.begin(), a.end(), x) > target; }
);

new_end等于a.end()。调试器将此值打印为垃圾。但在你的情况下偶然it happens to just works

正如多位评论员指出的那样,一旦您的谓词返回true一次,范围[a.begin()a.end)就会被修改,而最后一个元素的值未指定 1

这会使std::count(a.begin(), a.end(), x)返回未指定的值。

建议的解决方法是在a开始移动之前制作remove_if的副本。这是通过按值捕获它来完成的:

auto new_end = std::remove_if(a.begin(), a.end(),
    [b=a, target](const int x) { return std::count(b.begin(), b.end(), x) > target; }
);

将副本初始化为新名称b只是强调它是副本。

1)来自std::remove_if

  

指向新逻辑端和范围的物理端之间的元素的迭代器仍然是可解除引用的,但元素本身具有未指定的值(根据MoveAssignable后置条件)。

答案 1 :(得分:-2)

我假设要从vector中删除大于9的数字,这是代码

    vector<int> a = { 2, 7, 11, 15 };
    int target = 9;

    auto new_end = std::remove_if(a.begin(), a.end(), [](const int x)
    {
        return x > 9;

    });
    a.erase(new_end, a.end());
    return 0;

lambda论证&#39; x&#39;将由remove_if提供,您不需要在捕获列表中添加任何内容