<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 );

相关推荐
遇乐的果园17 小时前
前端学习笔记-vue状态管理优化
前端·笔记·学习
从零开始的代码生活_17 小时前
C++ 继承详解:访问控制、对象模型、菱形继承与设计取舍
开发语言·c++·后端·学习·算法
云小逸17 小时前
【C++ 第七阶段:模板、泛型编程与工程综合详解】
开发语言·c++
可乐奶茶sky18 小时前
AI Agent 学习
人工智能·学习
GIS阵地18 小时前
QgsSingleBandPseudoColorRenderer 完整详解(QGIS 3.40.13 C++)
开发语言·前端·c++·qt·qgis
王维同学18 小时前
[原创][Windows C++]LSA 认证、安全与通知包的注册表枚举
c++·windows·安全
茯苓gao18 小时前
嵌入式开发笔记:EtherCAT协议从硬件到软件完整配置指南——从零搭建一套EtherCAT通信系统
笔记·嵌入式硬件·学习
_wyt00119 小时前
完全背包问题详解
c++·背包dp
RD_daoyi20 小时前
外链权重暴跌至13%,品牌提及反超传统链接——2026年不做Digital PR,你的独立站等于隐形
运维·网络·学习·机器学习·搜索引擎
chase。20 小时前
【学习笔记】PointWorld:迈向通用机器人操控的3D世界模型
笔记·学习·机器人