set是自动排序、去重的只读关联容器,基于红黑树实现,插入/查找/删除均为o(log n);insert返回pair以标识是否新插入成功,second为false表示元素已存在,first指向原元素;忽略second易导致逻辑错误。

直接说结论:set 是自动排序、去重的只读集合,不能改元素值,插入/查找/删除都是 O(log n);用错场景或强行改值会编译失败或逻辑出错。
为什么 insert 返回 pair
因为 set 必须保证元素唯一,insert 不是“一定加进去”,而是“尝试加入”。返回值 pair<iterator bool></iterator> 中:
-
second为true表示新元素成功插入(之前不存在) -
second为false表示元素已存在,first指向那个已有元素
常见错误是忽略 second 直接用 first,结果误以为插入成功。例如:
set<int> s; auto p = s.insert(5); *p.first = 10; // 编译错误!*p.first 是 const int& </int>
erase 有三种重载,别混用
erase 根据参数类型行为完全不同,容易误删或静默失败:
-
s.erase(key):删值,返回删了几个(set 中只能是 0 或 1) -
s.erase(iter):删迭代器所指位置,返回下一个有效迭代器(可用于循环中安全删除) -
s.erase(first, last):删左闭右开区间,last必须可达且不等于end(),否则未定义行为
典型坑:s.erase(s.find(3)) 如果 3 不存在,find 返回 s.end(),传给 erase(iter) 会崩溃。应先判空:
auto it = s.find(3); if (it != s.end()) s.erase(it);
find 和 count 都能判断存在性,但用途不同
find 返回迭代器,适合需要后续操作(比如删、取值、做 lower_bound 基准);count 只返回 0 或 1,语义更清晰但无额外信息。
- 想“如果存在就删掉” → 用
find+ 判空 +erase(iter) - 只关心“有没有”,比如做条件分支 →
if (s.count(x))更直白
注意:count 在 set 中永远最多返回 1,和 multiset 不同;别指望它统计频次。
自定义类型必须提供比较规则
set 要排序,所以类型必须可比较。内置类型(int、string)默认支持;自定义结构体必须:
- 重载
operator(推荐),或 - 传入比较函数对象,如
set<person decltype> s(cmp)</person>
漏掉比较规则会导致编译错误,提示类似 “no match for ‘operator 替代 就会破坏红黑树结构。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











