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

相关推荐
蒸蒸yyyyzwd1 小时前
后端学习笔记 day111
笔记·学习
叼烟扛炮1 小时前
[LangChain] 学习笔记(08):工具调用底层闭环与第三方搜索(Tavily)实战
人工智能·笔记·学习·langchain
Severus_black2 小时前
【C++初阶】list使用及相关实现,思路顺滑流畅!
c语言·数据结构·c++·stl·list
Century_Dragon2 小时前
让新能源故障诊断实训“触手可及“——仿真教学软件(VR)介绍
学习
楚山之石3 小时前
【Radiology】影像组学的标准化与可重复性:IBSI 卷积滤波器共识及其未能覆盖的环节
人工智能·学习·机器学习·mri
秋天的怀念_David3 小时前
算法一千零一夜 · 第二十八夜 注册
java·程序人生·算法
敲上瘾3 小时前
Qt Widgets入门:项目模板解析与Hello World
开发语言·数据库·c++·qt·ui·qt6.3
小李不想当小白4 小时前
HAL库之UART(STM32 HAL库学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习·嵌入式
旖旎夜光5 小时前
【C++ 基础入门】C++ 多态(中):虚函数表、多态原理与动静绑定
开发语言·c++·笔记·学习
旖旎夜光6 小时前
【C++ 基础入门】C++多态(下):单/多继承虚表、多态补充与 21 道高频题
开发语言·c++·笔记·学习