std::set天然去重并升序排序,重复insert()静默失败且返回pair.second为false;降序需显式指定std::greater;自定义比较器时find/count必须遵循相同逻辑。

std::set 在 C++ 中天然支持去重和升序排序,无需额外逻辑 —— 但前提是元素类型满足可比较(operator 或自定义比较器),且你没误用 <code>std::multiset 或手动插入重复值。
为什么插入重复元素后 size 没变?
这是 std::set 的正常行为:它只保留唯一值,重复 insert() 调用会静默失败(返回 std::pair<iterator bool></iterator> 中的 false)。常见误判是只看返回值不检查 second 字段:
std::set<int> s; auto res = s.insert(5); // res.second == true res = s.insert(5); // res.second == false → 此时 size 仍为 1
- 别依赖
s.size()变化来判断是否新增成功,应检查insert()返回值的second - 若需批量去重并保持原始顺序,
std::set不适用 —— 改用std::unordered_set+std::vector记录顺序 -
std::set插入复杂度是O(log n),高频插入场景注意性能瓶颈
如何让 set 按降序排列?
默认使用 std::less<t></t>(即 ),要降序只需换比较器:<code>std::greater<t></t>:
std::set<int, std::greater<int>> desc_set;
desc_set.insert({3, 1, 4, 1, 5}); // 实际存为 {5,4,3,1}
- 比较器类型必须在模板参数中显式写出,不能运行时切换
- 自定义类型需提供对应比较逻辑:要么重载
operator>,要么传入 lambda(C++20 起支持,但需用std::set<t decltype></t>形式) - 若仅需一次排序输出,用
std::vector+std::sort更灵活;std::set的排序是“持续维护”的开销
字符串去重时大小写敏感怎么办?
std::set<:string></:string> 默认按字典序区分大小写("Apple" ≠ "apple")。若需忽略大小写去重,不能直接用默认比较器:
立即学习“C++免费学习笔记(深入)”;
- 方案一:插入前统一转小写(
std::transform+std::tolower),但丢失原始大小写形式 - 方案二:自定义比较器,内部做 case-insensitive 比较(注意 locale 安全,简单 ASCII 场景可用
std::tolower) - 方案三:用
std::unordered_set配合哈希策略,更高效但无序 —— 若只要去重不要排序,这是更优解
真正容易被忽略的是:一旦用了自定义比较器,find()、count() 等操作必须保证传入的 key 满足相同比较逻辑,否则查不到 —— 比如大小写不敏感比较器下,用 "HELLO" 去 find("hello") 才有效,反之亦然。











