set_intersection 是定义在 中的泛型算法,要求两输入范围必须已升序排序,适用于 vector、set 等有序容器,返回输出区间新末尾,需配合 back_inserter 或预分配空间使用。

set_intersection 是算法,不是 set 的成员函数
很多人搜 set_intersection_c++,以为它是 std::set 的某个成员方法,实际它在 <algorithm></algorithm> 头文件里,是泛型算法,适用于任何满足“有序范围”要求的容器(比如 std::vector、std::set、std::array),不绑定于 std::set 本身。
它的核心限制是:两个输入范围**必须已升序排序**,否则行为未定义 —— 这也是最常踩的坑。
-
std::set天然有序,可直接用;但std::unordered_set不行,得先转成 vector 再排序 - 如果数据来自用户输入或外部 API,别假设它已排序,务必检查或显式排序
- 交集结果写入目标迭代器前,目标容器需有足够空间,或用
std::back_inserter
正确调用 set_intersection 的三要素
调用 std::set_intersection 必须提供:两个输入范围的起止迭代器 + 输出起始迭代器。它返回输出区间的“新末尾”,不是 void。
常见错误写法:set_intersection(a.begin(), a.end(), b.begin(), b.end(), out.begin()) —— 如果 out 容量不够,会越界写入。
立即学习“C++免费学习笔记(深入)”;
- 安全做法:用
std::vector接收,配合std::back_inserterstd::vector<int> result;<br>std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(result));
- 若确定最大可能大小(如取 min(size_a, size_b)),可预分配:
result.resize(std::min(a.size(), b.size()));,再用result.begin()作输出起点,最后用返回值截断:result.resize(it - result.begin()); - 支持自定义比较器,比如降序集合:
std::set_intersection(a.rbegin(), a.rend(), b.rbegin(), b.rend(), ..., std::greater<int>{})</int>,注意迭代器类型要匹配(反向迭代器)
和 set 成员函数 find/insert 比,性能差在哪?
std::set_intersection 是双指针 O(m+n) 时间复杂度,而手动遍历 + find 是 O(m log n),看起来前者更优。但实际中,如果只求一次交集且集合很小(比如都
-
std::set::find内部是红黑树查找,常数较大;但现代 CPU 对小数据局部性好,未必慢 -
std::set_intersection要求输入严格有序,如果数据本就无序,排序成本(O(n log n))会吃掉优势 - 若需去重后的交集且输入是 vector,先
sort + unique再用set_intersection,比塞进std::set再遍历更轻量
处理自定义类型时,比较器必须一致
如果你的 std::set<mystruct></mystruct> 用 Compare 自定义排序,那么 set_intersection 的第 5 个参数也必须传同一个(或语义等价的)比较器。否则结果错乱,且不会报错。
例如:
struct Person { int id; std::string name; };<br>auto cmp = [](const Person& a, const Person& b) { return a.id < b.id; };<br>std::set<Person, decltype(cmp)> s1(cmp), s2(cmp);<br>// ✅ 正确<br>std::vector<Person> res;<br>std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(),<br> std::back_inserter(res), cmp);- 漏传比较器,编译可能通过(用默认
operator),但逻辑错误 - 传了不同逻辑的比较器(比如按 name 排序却用 id 比较),结果不可预测
- lambda 比较器不能直接用于模板推导,必须显式传参或用
decltype声明类型
实际用的时候,先确认数据是否真有序、目标容器是否可增长、比较逻辑是否统一 —— 这三点没对齐,set_intersection 就容易静默出错。











