使用remove_if从向量中删除元素

wai*_*r92 11 c++ stl vector c++11

我试图删除矢量元素使用remove_if.但没有成功.我究竟做错了什么?

这是我的代码:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

void printme(std::vector<int>& a){
    for(const auto& item: a)
    std::cout << item << std::endl;
}

int main()
{
    std::vector<int> a {1, 2, 3, 4, 5, 6};
    printme(a);  
    a.erase( (std::remove_if(a.begin(), a.end(), [](const int& x){
        return x == 2;
        }), a.end()));
    printme(a);
}
Run Code Online (Sandbox Code Playgroud)

我的输出只是:

1 2 3 4 5 6

预期产量:

1 2 3 4 5 6 1 3 4 5 6

眠りネ*_*ネロク 19

您正在使用std::vector::erase()成员函数的重载,该函数将单个迭代器作为参数.由于erase()您的参数是提供迭代器a.end(),因为以下表达式:

(std::remove_if(a.begin(), a.end(), [](const int& x){ return x == 2; }), a.end()))
Run Code Online (Sandbox Code Playgroud)

评估为a.end()(即,因为逗号运算符).

传递给迭代器的迭代器erase()需要一个迭代器才能解除引用.但是,迭代器a.end()不能解除引用,因此,调用会erase()导致未定义的行为.


要使用带有两个迭代器的重载,请删除调用周围的括号std::remove_if:

a.erase(std::remove_if(a.begin(), a.end(), [](const int& x){
        return x == 2;
        }), a.end());
Run Code Online (Sandbox Code Playgroud)

  • 这里的教训是,单行是危险的,因为它们很难阅读.将调用分离为`std :: remove_if`和`a.erase`可以使代码更清晰. (10认同)

son*_*yao 8

您正在添加多余的括号,将其更改为

a.erase( std::remove_if(a.begin(), a.end(), [](const int& x){
    return x == 2;
    }), a.end());
Run Code Online (Sandbox Code Playgroud)

需要注意的是逗号操作只是返回最后一个操作数,这意味着你传递a.end()erase,从而导致UB.


R S*_*ahu 7

其他答案指出了问题所在.我想说,通过简化代码可以更容易地注意到这些问题.

我建议使用:

int main()
{
   std::vector<int> a {1, 2, 3, 4, 5, 6};
   printme(a);  

   auto it = std::remove_if(a.begin(), a.end(), [](const int& x){ return x == 2; });
   a.erase(it, a.end());

   printme(a);
}
Run Code Online (Sandbox Code Playgroud)

  • 其他人也更容易理解您的代码. (4认同)

Pet*_*and 5

你在函数调用中只有太多的括号.

a.erase(std::remove_if(a.begin(), a.end(), [](const int& x) {return x == 2;}), a.end());
Run Code Online (Sandbox Code Playgroud)

只需std::remove_if在通话结束前和通话结束时删除一个括号即可.