c++ - 有没有更好的替代 std::remove_if 从 vector 中删除元素的方法?

标签 c++ c++11 stl c++17 erase-remove-idiom

std::vector 或其他容器中删除具有特定属性的元素的任务适用于函数式实现:为什么要为循环、内存释放和正确移动数据而烦恼?

但是,在 C++ 中执行此操作的标准方法似乎是以下习惯用法:

std::vector<int> ints;
...
ints.erase(
    std::remove_if(ints.begin(), 
                   ints.end(),
                   [](int x){return x < 0;}),
    ints.end());

此示例从整数 vector 中删除所有小于零的元素。

我觉得它不仅丑而且容易用错。很明显 std::remove_if 不能改变 vector 的大小(正如它的名字所暗示的那样),因为它只会传递迭代器。但包括我自己在内的许多开发人员一开始并没有意识到这一点。

那么有没有一种更安全、更有希望更优雅的方法来实现这一点?如果不是,为什么?

最佳答案

I find it not only ugly but also easy to use incorrectly.

别担心,我们一开始都是这样做的。

It is clear that std::remove_if cannot change the size of the vector (as its name would suggest) because it only gets iterators passed. But many developers, including myself, don't get that in the beginning.

一样。它让每个人都感到困惑。那些年前它可能不应该被称为 remove_if 。事后诸葛亮,嗯?

So is there a safer and hopefully more elegant way to achieve this?

没有

If not, why?

因为这是在从容器中删除项目时保持性能的最安全、最优雅的方式,在该容器中删除项目会使迭代器失效。

预期:

Anything I can do?

是的,把这个成语包装成一个函数

template<class Container, class F>
auto erase_where(Container& c, F&& f)
{
    return c.erase(std::remove_if(c.begin(), 
                                  c.end(),
                                  std::forward<F>(f)),
                   c.end());    
}

激励示例中的调用变为:

auto is_negative = [](int x){return x < 0;};
erase_where(ints, is_negative);

erase_where(ints, [](int x){return x < 0;});

关于c++ - 有没有更好的替代 std::remove_if 从 vector 中删除元素的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36384571/

相关文章:

c++ - C++ 上的预处理器重载

c++ - std::remove 和 std::remove_if 设计的稳定性是否失败?

c++ - 在 std::map 中插入模板化类,并在插入时进行构造

c++11 - std::move() 只是类型转换?

c++ - 适用于 STL 容器的简单 C++ 模板

c++ - C++ 中的 STL 容器实际上是如何实现的..

c++ - 在 C++ 中使用抽象基类和模板进行重构

c++ - 如何获取在 QGraphicsView 中加载的图像像素位置 - 奇怪的 MapToScene() 行为

c++ - 为什么 std::queue 在使用 swap() 时不释放内存?

c++ - STL priority_queue<pair> 与 map