std::set_symmetric_difference要求输入范围严格升序且谓词一致,目标容器不可为set的直接迭代器,须用inserter或back_inserter;手动实现需防迭代器失效。

std::set_symmetric_difference 要求输入已排序
直接调用 std::set_symmetric_difference 是最常用方式,但它不关心容器类型,只依赖迭代器的有序性。而 std::set 的迭代器天然升序,这点没问题;但如果你误传了未排序的 std::vector 或手动构造的乱序范围,结果就是错的——函数不会报错,只会输出无意义数据。
- 必须确保两个输入范围都严格升序(
std::set默认满足) - 目标容器需预留足够空间,或用
std::back_inserter(否则写入越界) - 比较谓词要一致:若
std::set自定义了比较器(如std::greater<int></int>),std::set_symmetric_difference也得传同样的谓词
目标容器不能是 std::set 且直接 insert
你不能把 std::set_symmetric_difference 的输出迭代器直接设为某个 std::set<t>::iterator</t>——因为 std::set 的迭代器是 const 的,不支持赋值写入。常见错误是写成:std::set_symmetric_difference(a.begin(), a.end(), b.begin(), b.end(), result.begin()),这会编译失败(assignment of read-only location)。
- 正确做法是用
std::inserter(result, result.end())或std::back_inserter(vec) - 如果目标是
std::set,优先选std::inserter;如果后续要频繁随机访问,用std::vector+back_inserter更快 -
std::inserter内部调用insert(),时间复杂度 O(m log n),比先写进 vector 再建 set 略慢但更直观
手动实现时注意 erase() 迭代器失效
有人想“先合并再去重”,比如把两个 std::set 插入一个临时 std::multiset,再删掉出现两次的元素。这容易踩坑:erase(iterator) 后,该迭代器立即失效,继续 ++ 会 UB。
- 安全做法是用
erase(it++)(后置++ 返回旧值,erase 后 it 已更新) - 更稳妥的是遍历计数 map:
std::map<t int> count</t>,然后收集 value == 1 的 key - 别用
std::set::erase(key)清单式删除,它返回删除个数,无法定位具体哪些元素该留
性能差异:std::set vs vector + sort + unique
对小数据(std::set 直接操作更简单;但大数据下,std::set 的节点分配和指针跳转开销明显高于连续内存。实测 10⁵ 元素时,转 std::vector → merge → std::unique 比双 std::set 遍历快 2–3 倍。
- 转换路径:
vec_a.assign(s1.begin(), s1.end()),同理 vec_b;然后std::merge+std::unique - 注意
std::unique只移除相邻重复项,所以 merge 后必须保证整体有序(std::merge保证这点) - 如果原始 set 很大且只用一次对称差,避免拷贝——坚持用
std::set_symmetric_difference+std::inserter更省心
std::set、是否在意常数级性能、以及目标容器类型是否固定。没有银弹,但 std::set_symmetric_difference 配 std::inserter 是最不容易出错的起点。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











