Effective STL 21 比较函数等值情况下返回false
set
s.insert(10); //A
再次
s.insert(10); //B
关联容器在insert 或者sort 时会检查是否等价(详见Effective 19条),所以集合会测试是否等价,测试时就用到该容器的比较函数,遍历容器找到合适位置,然后进行测试。
测试公式就是 公式 = !(w<x) && !(x<w) “<” 就用我们重载的比较函数替换,比较函数实现一般有三种方式,我们拿重载operator<来举例。
如果 公式==false 就是不等价,可以插入;
如果 公式==true 就是等价, 不可以插入;
例子中 !(10A<=10B)&&!(10B<=10A) !true && !true ->false && false ->结果是false ,可以插入,那就是有两个10,不再是一个集合。破坏了set容器!
任何一个比较函数,如果相等的值返回true(指的是比较函数),从技术上的角度,这会导致不确定的行为。按照定义,相等的值是不等价的,这是错误的!
multiset 允许重复的值,认为等值不等价,又有什么关系呢? 反正都要保存起来。
这样也是不对的,还是看例子
multiset
s.insert(10);
s.insert(10);
现在s中保存了二个值,如果我们对它做equal_range 操作,则将得到一对迭代器,迭代器得到的是包含等价值的区间,而不是包含相等值的区间。
此列中10A 和10B 不等价,所以不可能都在区间内。
所以一句话的结论: <等值情况下, 比较函数返回false,等价公式返回的就是true(!false && !false) >
【以下为推测,没有去验证源代码】
所以 set ,map. 以下面为比较函数情形.
点击(此处)折叠或打开
-
struct {
-
-
int a;
-
-
bool operator<(const type &rhs)
-
{
- return if(a<rhs.a) /*升序*/
-
//return if(rhs.a<a) /*降序*/
-
}
- }
return ; //等价不允许插入,(multiset multimap 这里处理肯定不一样)
if(比较函数)== true
//插入当前点后面(右结点)
else
//插入当前点前面(左结点)
至此, 这个问题就清楚了,等价检查返回的true,
所以不能插入第二条。
bool operator <(tag_GTPC_KEY const& rhs) const
{
if(Ipv4 < rhs.Ipv4 ||
(Ipv4 == rhs.Ipv4 && (Ipv6 < rhs.Ipv6
||(Ipv6 == rhs.Ipv6 && (Teid < rhs.Teid
|| (Teid == rhs.Teid && (BerID < rhs.BerID)))))))
return true;
return false;
}
所以不能插入第二条。
bool operator <(tag_GTPC_KEY const& rhs) const
{
if(Ipv4 < rhs.Ipv4 ||
(Ipv4 == rhs.Ipv4 && (Ipv6 < rhs.Ipv6
||(Ipv6 == rhs.Ipv6 && (Teid < rhs.Teid
|| (Teid == rhs.Teid && (BerID < rhs.BerID)))))))
return true;
return false;
}
多元素比较函数模板
点击(此处)折叠或打开
-
if(a<rhs.a ||
-
(a==rhs.a && (b<rhs.b ||
-
(b==rhs.b && (c<rhs.c )))))
-
-
return true;
- return false;
从第一个元素开始检查, 相等的话,检查第二个,第二个相等的话,检查第三个......
第一个检查元素权重最高,a b c d 依次类推......
条件检查从前往后,只要有一个true 就成立,后面不用检查。
再上升一下,用数学原理还是什么的解释待学习。有了解给补充一下或提示一下。谢谢!