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

相关推荐
小陈phd19 分钟前
Text2SQL智能体学习笔记(一)——NL2SQL及执行流程介绍
笔记·学习
风栖柳白杨19 分钟前
【大模型学习】主流大模型统计
学习
lengxuemo21 分钟前
ICC2学习之PG
学习
稷下元歌23 分钟前
系统学习plc 基础指令上篇,官方资料课程笔记整 理
笔记·学习
我的xiaodoujiao24 分钟前
API 接口自动化测试详细图文教程学习系列25--继续处理testCase中的数据
python·学习·测试工具·pytest
你的保护色29 分钟前
数据库第一章-基础知识学习
数据库·学习
数智工坊37 分钟前
【ROS 2 全栈入门指南一】:从本质认知到环境搭建与核心原理解析
学习·机器人
攻城狮Soar1 小时前
STL源码解析之list(1)
开发语言·c++
2401_869769591 小时前
内容5 日期类实现
开发语言·c++
xxwl5851 小时前
一个原创题(二)
c++·算法