自定义对象必须提供可比较逻辑,否则 set 编译失败;默认情况下,set 要求元素支持 operator
自定义对象必须提供可比较逻辑,否则
set编译失败默认情况下,
set要求元素支持比较(用于红黑树排序)。如果你直接把一个没重载 <code>operator 的结构体或类塞进 <code>set,编译器会报类似这样的错:invalid operands to binary expression ('const MyObj' and 'const MyObj')。最直接的解法是在类内定义
operator:struct Person { std::string name; int age; bool operator <p>注意:必须加 <code>const</code> 修饰符,且参数和函数本身都要是 <code>const</code>,否则 <code>set</code> 内部调用时可能不通过。</p> <h3>用仿函数(Functor)替代 <code>operator 更灵活</code> </h3> <p>当不想修改原类、或需要多种排序方式(比如按姓名升序、按年龄降序),就该用自定义比较器。它本质是一个重载了 <code>operator()</code> 的结构体或 lambda(C++11+):</p> <pre class="brush:php;toolbar:false;">struct CompareByName { bool operator()(const Person& a, const Person& b) const { return a.name nameSet;或者用 lambda(需用
std::function包装,但更常见的是在构造时传入,仅限 C++11+):auto cmp = [](const Person& a, const Person& b) { return a.age > b.age; }; // 降序 std::set<person decltype> ageDescSet(cmp);</person>注意:lambda 类型不能直接写在模板参数里(除非用
auto推导或std::function),所以通常只在构造时传入。使用
std::tuple或std::tie简化多字段比较多个字段排序容易写错逻辑(比如漏掉
return、顺序颠倒)。用std::tie可以一行写出字典序比较:bool operator <p>这等价于先比 <code>age</code>,相等再比 <code>name</code>,且自动处理类型兼容性。只要字段类型都支持 <code>,就没问题。</code></p> <p>注意事项:</p>
std::tie返回的是引用元组,不拷贝数据,效率高- 字段顺序决定优先级,别把次要字段放前面
- 如果某个字段是自定义类型,它自己也得能比较
插入重复对象会被自动忽略,且无法通过下标访问
set是唯一键容器,两个对象若a 和 <code>b 都为 <code>false,就视为相等,后插入的会被丢弃。这点和vector完全不同。你不能写
mySet[0]或mySet[i]——set不支持随机访问。要遍历只能用迭代器:for (const auto& p : mySet) { std::cout <p>如果需要按索引查,要么转成 <code>vector</code>(失去 O(log n) 插入优势),要么用 <code>std::map</code> 手动维护索引——但那已经不是 <code>set</code> 的职责了。</p> <p>真正容易被忽略的是:比较逻辑一旦写错(比如 <code>operator 不满足严格弱序),<code>set</code> 行为未定义——可能崩溃、卡死、或看似正常但结果错乱。务必保证对任意 a,b,c,<code>a<b> 和 <code>b<a> 不同时为真,且传递性成立。</a></code></b></code></code></p>
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!












