std::set_intersection要求两输入区间必须已升序排序且谓词一致,输出需用支持赋值的迭代器(如back_inserter),不可直接输出到std::set。

std::set_intersection要求输入必须是已排序区间
这个函数不会自动排序,只做归并交集计算。如果传入未排序的 std::vector 或原始数组,结果不可预测,甚至可能崩溃(比如越界读取)。它本质是双指针遍历,依赖两个序列都升序排列。
常见错误现象:std::set_intersection 返回的迭代器指向空容器,或输出一堆重复/乱序值,其实是输入没排好序导致的逻辑错位。
- 使用前务必对两个输入容器调用
std::sort(若底层是std::vector)或确认它们来自std::set/std::multiset -
std::set本身有序,所以直接用其begin()/end()是安全的;但注意std::set迭代器是 const 的,不能作为输出目标 - 输出容器(如
std::vector)必须预留足够空间,或用std::back_inserter动态追加
输出目标必须支持写入,不能直接用 set::insert_iterator
std::set_intersection 的第三个参数是输出迭代器,它会通过 *it++ = value 赋值。而 std::set 的插入必须走 insert(),它的迭代器不支持赋值操作——所以不能把 std::inserter(my_set, my_set.end()) 直接传进去,编译会失败。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
典型错误信息:error: no match for 'operator='(针对 std::set<int>::iterator</int>)。
- 安全做法:先输出到
std::vector,再用循环或std::for_each插入到std::set - 若只需去重结果且不在乎顺序,可改用
std::unordered_set+ 手动遍历,但失去 O(n+m) 时间优势 - 用
std::back_inserter(my_vec)最省心,my_vec无需预分配大小
注意比较谓词必须一致,尤其自定义类型
如果你用 std::set<mystruct std::greater>></mystruct> 或带自定义 Compare 的 std::vector,那么 std::set_intersection 的第五个参数(谓词)必须和排序时用的完全一致。否则交集逻辑错乱——比如一个按升序排、另一个传了 std::greater,函数会误判“相等”。
- 内置类型(
int,std::string)默认用std::less,即,一般不用显式传参 - 自定义类型务必核对:排序用的
Compare类型、函数对象、lambda 是否和set_intersection中的一致 - lambda 捕获变量需注意生命周期;临时 lambda 若绑定局部引用,可能引发未定义行为
性能关键点:避免多余拷贝和重复分配
在高频调用或大数据量场景下,反复 clear() + reserve() + back_inserter 可能比预分配更慢,因为 std::vector::push_back 触发多次内存重分配。
- 若交集大小可预估(例如知道两集合大小上限),直接
vec.resize(std::min(a.size(), b.size())),再用普通迭代器传入,最后用vec.erase(it_end, vec.end())截断 - 避免对同一容器反复构造
std::back_inserter——它只是轻量包装,但语义上每次都是新对象 - 若输入是
std::set且只读,考虑用std::set::find遍历小集合查大集合,代码更直观,且对小数据反而更快(避免归并开销)
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










