好了,先贴一段英文,真心不想翻译过来,而且感觉也翻译不到那么到位:

The STL is awash in comparisons of objects to see if they have the same value. For example, when you ask find to locate the first object in a range with a particular value, find has to be able to compare two objects to see if the value of one is the same as the value of the other. Similarly, when you attempt to insert a new element into a set, set::insert has to be able to determine whether that element’s value is already in the set.

The find algorithm and set’s insert member function are representative of many functions that must determine whether two values are the same. Yet they do it in different ways. find’s definition of “the same” is equality, which is based on operator==. set::insert’s definition of “the same” is equivalence, which is usually based on operator<.

Operationally, the notion of equality is based on operator==. If the expression “x == y” returns true, x and y have equal values, otherwise they don’t.

x and y have equivalent values with respect to operator< if the following expression is true:

!(x < y) && !(y < x)

好了,关于等价和等值的讨论,我们先到此为止。我们引入下一话题,假设我们现在创建如下一个set:

set<int, less_equal<int> > s; // s is sorted by “<=”

向其中插入10:

s.insert();

然后再向其插入10,我们知道,set中的元素是没有重复的,所以程序会判断10是否已经在当前set中,为了方便说明,我们把第一个插入的10称为10A,第二个称为10B。set的判断过程会是10A和10B是否是一样的,set所定义的一样就是我们之前提到的equivalence

那么程序中的less_equal是怎么来判断的呢?我们根据上面的推导,一个合理的推导,set可能是这样来判断的:

!(10A <= 10B) && !(10B <= 10A)      // test 10A and 10B for equivalence

当然上头的判定的结果为:!(true) && !(true) ,等价于 false && false,所以最终的结果会是false,也就是说,判定结果告诉我们,10A和10B is not equivalent!然后10B,也就是10会被再一次插入到set中,oh, no!

好了,这只是个玩笑,set可不会弱到如此地步,set中是不会存在重复元素的。小伙伴们肯定觉得疑惑了,这说了半天有毛用啊,set又不会使用less_equal这样的顺序,因为压根就不允许equal的情况发生,你这不是找别扭呢嘛!

别急,set有不重复这个特性,那么要是是个multiset呢,按照这个思路,这样的操作一定会成功,会认为是两个不同的元素插入到multiset内部,假设我们在后面需要做equal_range的相关操作(it identifies a range of equivalent values),问题就大了!

哈哈,和大家开了个很大的玩笑,STL是经过千锤百炼的,怎么可能存在这样傻的问题!关于这个问题SGI是最权威的了,我们可以去SGI查查,看到底是怎么回事!还真有,关键字:Strict Weak Ordering,好了让我们看看是怎么解决这个问题的:

明白了吧,人家是避免<=这样的比较出现,怎样避免?我目前认为避免的意思就是不能这样,这样就不行,看代码吧:

multiset<int, less_equal<int> > s;
s.insert();
s.insert();

这段代码编译通过,但是执行时会报assert错误!我没有搞清楚其中的原理,继续研究吧!

好了,绕了这么一大圈,其实就是想告诉你,在实现自己的类似less_equal仿函数的时候,一定要留神了,千万不要存在这样的bug!

感谢大家的阅读,希望能帮到大家!

Published by Windows Live Writer.

C++之Effective STL学习笔记Item21的更多相关文章

  1. Effective STL 学习笔记 39 ~ 41

    Effective STL 学习笔记 39 ~ 41 */--> div.org-src-container { font-size: 85%; font-family: monospace; ...

  2. Effective STL 学习笔记 Item 38 : Design functor classes for pass-by-value

    Effective STL 学习笔记 Item 38 : Design functor classes for pass-by-value */--> div.org-src-container ...

  3. Effective STL 学习笔记 Item 34: 了解哪些算法希望输入有序数据

    Effective STL 学习笔记 Item 34: 了解哪些算法希望输入有序数据 */--> div.org-src-container { font-size: 85%; font-fam ...

  4. Effective STL 学习笔记 32 ~ 33

    Effective STL 学习笔记 32 ~ 33 */--> div.org-src-container { font-size: 85%; font-family: monospace; ...

  5. Effective STL 学习笔记 31:排序算法

    Effective STL 学习笔记 31:排序算法 */--> div.org-src-container { font-size: 85%; font-family: monospace; ...

  6. Effective STL 学习笔记 Item 30: 保证目标区间足够大

    Effective STL 学习笔记 Item 30: 保证目标区间足够大 */--> div.org-src-container { font-size: 85%; font-family: ...

  7. Effective STL 学习笔记 Item 26: Prefer Iterator to reverse_iterator and const_rever_itertor

    Effective STL 学习笔记 Item 26: Prefer Iterator to reverse_iterator and const_rever_itertor */--> div ...

  8. Effective STL 学习笔记: Item 22 ~ 24

    Effective STL 学习笔记: Item 22 ~ 24 */--> div.org-src-container { font-size: 85%; font-family: monos ...

  9. Effective STL 学习笔记 Item 21:Comparison Function 相关

    Effective STL 学习笔记 Item 21:Comparison Function 相关 */--> div.org-src-container { font-size: 85%; f ...

随机推荐

  1. HDU 1847 Good Luck in CET-4 Everybody! 四级好运!(博弈)

    思路:先用P/N状态来找规律. N状态:1 2 4 6 8 16 P状态:3 5 因为3=1+2, 无论拿1或者2皆输.看看5,只要抽掉2就变成了3,所以是N状态.看看6,可以抽掉1 2 4,若抽1, ...

  2. Codeforces 724 G Xor-matic Number of the Graph 线性基+DFS

    G. Xor-matic Number of the Graph http://codeforces.com/problemset/problem/724/G 题意:给你一张无向图.定义一个无序三元组 ...

  3. opencv c++编译

    g++ image2png.cpp -o test `pkg-config --cflags --libs opencv`

  4. python之文件操作的初识

    1. 操作文件 1.1 操作的方法 f = open("文件路径",mode="模式",encoding="编码") open() # 调用 ...

  5. python特殊字符转义符号表示

  6. 转 消息队列之 RabbitMQ

    转 https://www.jianshu.com/p/79ca08116d57 消息队列之 RabbitMQ 预流 2017.05.06 16:03* 字数 4884 阅读 80990评论 18喜欢 ...

  7. Laravel常用命令

    php artisan make:controller BlogController php artisan make:model Blog

  8. 学习路由器vue-router

    vue-router:vue官方路由管理器. 功能:嵌套的路由/视图表模块化的.基于组件的路由配置路由参数.查询.通配符基于 Vue.js 过渡系统的视图过渡效果细粒度的导航控制带有自动激活的 CSS ...

  9. 【js】【vue】获取当前dom层

    多层嵌套,$event.currentTarget 指当前点击层

  10. F查询与Q查询

    F查询 如果我们要对两个字段的值做比较,那该怎么做呢? Django 提供 F() 来做这样的比较.F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值. # 查询评论 ...