<algorithm> 中 remove、remove_if、remove_copy、remove_copy_if 详解

  • 本文所有出现的Froward均属于前向迭代器类型(可重复读取),核心特点是不真正删除元素(仅做元素移动覆盖),需要结合容器的erase完成最终的删除
  • 核心逻辑是:
    • 遍历容器,将不需要的元素向前移动,覆盖需要移除的元素
    • 返回一个迭代器,指向移除后有效元素的末尾(待删除有效元素的起始位置)
    • 容器的实际大小不变,只是有效元素被重新排列,需得手动调用 erase 删除末尾无效元素

remove

功能: 删除指定元素

原型:

template<class ForwardIterator , class T>

ForwardIterator remove (ForwardIterator first , ForwardIterator last , const T& value);

参数解析:

first / last : 原容器起始/终止位置,last指向容器最后有效数据的下一位

value : 指定删除的值

返回值:指向新逻辑结尾的迭代器,类似一个包含value的合集位置

用法:

cpp 复制代码
vector<int> vec = { 1, 2, 3, 4, 5 ,6 };
auto newEnd  = remove (vec.begin(),vec.end(),2);  //此处newEnd内部是包含2的迭代器组合,vec中并未删除,只是查找

vec.erase(newEnd , vec.end());  //此处真正的删除在vec中

remove_if

功能:按条件删除元素

原型:

template<class ForwardIterator , class UnaryPredicate>

ForwardIterator remove (ForwardIterator first , ForwardIterator last , UnaryPredicate p);

参数解析:

first / last : 原容器起始/终止位置,last指向容器最后有效数据的下一位

p : 接收一元函数(返回bool)

返回值:指向新逻辑结尾的迭代器,返回true的合集位置

用法:

cpp 复制代码
vector<int> vec = { 1, 2, 3, 4, 5 ,6 };
auto isEven = [](int n) { return n % 2 == 0; }
auto newEnd  = remove_if (vec.begin(),vec.end(), isEven); 
vec.erase(newEnd , vec.end());  //此处真正的删除在vec中

remove_copy

功能:复制并删除指定值

原型:

template<class InputIterator, class OutputIterator, class T>

OutputIteratorremove (InputIteratorfirst , InputIteratorlast , OutputIterator result, const T& value);

参数解析:

first / last : 原容器起始/终止位置,last指向容器最后有效数据的下一位

result : 目标容器的起始迭代器

value : 要删除的值

返回值:指向目标容器最后写入元素的下一个位置

用法:

cpp 复制代码
vector<int> vec = { 1, 2, 3, 4, 5 ,6 };
vector<int> destVec;
destVec.resize( vec.size());
auto newEnd = remove_copy ( vec.begin(),vec.end(),destVec.begin(),2);
destVec.erase(newEnd , destVec.end());

remove_copy_if

功能:复制并按条件删除值

原型:

template<class InputIterator, class OutputIterator, class UnaryPredicate >

OutputIterator remove_copy_if (InputIteratorfirst , InputIteratorlast , OutputIterator result, UnaryPredicate p);

参数解析:

first / last : 原容器起始/终止位置,last指向容器最后有效数据的下一位

result : 目标容器的起始迭代器

p : 接收一元函数(返回bool)

返回值:指向目标容器最后写入元素的下一个位置

用法:

cpp 复制代码
vector<int> vec = { 1, 2, 3, 4, 5 ,6 };
vector<int> destVec;
destVec.resize( vec.size());
auto isEven = [](int n) { return n % 2 == 0; }
auto newEnd = remove_copy_if ( vec.begin(),vec.end(),destVec.begin(), [](int n) { return n % 2 == 0; });
//auto newEnd = remove_copy_if ( vec.begin(),vec.end(),destVec.begin(), isEven);
destVec.erase(newEnd , destVec.end());
  • remove / remove_if: ForwardIt ,前向迭代器,支持双向遍历
  • remove_copy / remove_copy_if : 输入迭代器读原容器,输出迭代器写新容器

C++11 关键细节

  • UnaryPredicate(条件函数)必须是纯函数,不能修改迭代器指向的元素,否则行为未定义
  • ForwardIterator指向的元素必须满足支持可移动赋值
  • 支持lambda,remove_if / remove_copy_if 的条件函数支持匿名lambda

C++17 并行化与约束强化

四个算法都支持算法并行化。在原型的基础上,每个原型都在第一参数位新增了ExecutionPolicy重载

  • ExexcutionPolicy : 必须是标准执行策略:std::execution::seq(串行)、std::execution::par(并行)、 std::execution::par_unseq(并行无序)
  • 并行版本要求FowardIt 满足随机语言访问迭代器,而非普通前向迭代器
  • UnaryPredicate必须是线程安全的(不能修改共享状态),否则行为未定义
  • remove_copy/remove_copy_if的OutputIt 若为par_unseq策略,需支持无序写入
  • remove_copy / remove_coy_if : InputIt指向元素必须是可拷贝构造,OutputIt指向的元素必须满足可拷贝赋值
  • 新增约束检查,用到std::is_move_assignable、std::is_copy_constructible等类型特性强化,编译器可提前检测错误
cpp 复制代码
 std::vector<int> vec = {1,2,3,4,5,6};
 auto newEnd = std::remove_if(std::execution::par, vec.begin(), vec.end(), [](int x){ return x%2 == 0; });
 vec.erase(new_end, vec.end());
 eturn 0;

C++20 Concepts约束

  • 核心改进
    • 错误提示精准:前期有执行策略合法检测、前向迭代器检测、以及迭代器内部是否可与T做比较的检测
    • 简化类型推导:std::iter_value_t替代typename std::iterator_traits::value_type,减少模板代码冗余
    • 单参约束强化: std::indirect_unary_predicate明确要求"可作用于迭代器解引用后的值",避免传入参数类型不匹配的参数

用remove原型做例,其他三个均如此

template <class ForwardIt , class T> requires

std::forward_iterator &&

std::indirect_binary_predicate<std::equal_to<>,ForwardIt, const T* >

// 显式要求前向迭代器 && 检查ForwardIt 是否与 T 可做比较

ForwardIt remove( ForwardIt first , ForwardIt last , const T& value );

template <class ExecutionPolicy , class ForwardIt , class T>

requires std::is_execution_policy_v<std::decay_t> &&

//合法执行策略 std::forward_iterator &&

std::indirect_binary_predicate<std::equal_to<>,ForwardIt, const T* >

// 显式要求前向迭代器 && 检查ForwardIt 是否与 T 可做比较 ForwardIt

remove(ExecutionPolicy&& exec , ForwardIt first , ForwardIt last , const T& value );

相关推荐
云边散步2 小时前
godot2D游戏教程系列二(13)
笔记·学习·游戏·游戏开发
gameboy0312 小时前
网络爬虫学习:应用selenium获取Edge浏览器版本号,自动下载对应版本msedgedriver,确保Edge浏览器顺利打开。
爬虫·学习·selenium
小蜗牛~向前冲2 小时前
大模型学习系列-Embedding与向量数据库
人工智能·python·神经网络·学习·机器学习·embedding
敬业小码哥2 小时前
记一次:clion使用rust插件配置环境并开发
学习·rust
华科易迅2 小时前
SQL学习
java·sql·学习
我头发还没掉光~2 小时前
【C++写详细总结①】从for循环到算法初步
数据结构·c++·算法
_李小白2 小时前
【AI大模型学习笔记之平台篇】第三篇:Minimax
人工智能·笔记·学习
寂静or沉默2 小时前
Ansible 学习总结
学习·ansible
【数据删除】3482 小时前
计算机复试学习笔记 Day41
笔记·学习·算法