- 本文所有出现的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 );