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

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. [学习总结] python语言学习总结 (一)

    还是不多说话了.. 1.eval函数 用法:eval(expression, globals=None, locals=None) 解释:将字符串str当成有效的表达式来求值并返回计算结果. 就是可以 ...

  2. Verilog设计分频器(面试必看)

    分频器是指使输出信号频率为输入信号频率整数分之一的电子电路.在许多电子设备中如电子钟.频率合成器等,需要各种不同频率的信号协同工作,常用的方法是以稳定度高的晶体振荡器为主振源,通过变换得到所需要的各种 ...

  3. 2018.4.11 Java为何用xml做配置文件? 理由如下

    在Java世界里xml配置文件几乎是首选,xml有什么好的特性呢? 第一:xml能存储小量数据,仅仅是存储数据. 第二:xml可以跨平台,主流各种平台都对xml有支持, 真正的跨平台, 第三:xml读 ...

  4. Java Marker Interface

    先看看什么是标记接口?标记接口有时也叫标签接口(Tag interface),即接口不包含任何方法. 在Java里很容易找到标记接口的例子,比如JDK里的Serializable接口就是一个标记接口. ...

  5. 洛谷 P1593 因子和

    https://www.luogu.org/problemnew/show/P1593#sub 利用约数和定理:可以去看一下公式第13条 然后这个题目的话,要求$a^b$,那么我们首先可以先将a分解然 ...

  6. shell 练习题 - 第三周

    1.编写脚本/root/bin/backup.sh,可实现每日将/etc/目录备份到 /root/etcYYYY-mm-dd中 #!/bin/bash echo "start backup& ...

  7. 装逼图片旋转合成demo

    测试背景 bg.jpg 测试图片 a.jpg 结果示例 代码demo <?php $bgImgFileName = 'bg.jpg'; $a = 'a.jpg'; // 初始化 $src = i ...

  8. 《Java并发编程实战》读书笔记一 -- 简介

    <Java并发编程实战>读书笔记一 -- 简介 并发的历史 并发的历史,也是人类利用有限的资源去提高生产效率的一个的例子. 设想现在有台计算机,这台计算机具有以下的资源: 单核CPU一个 ...

  9. 多进程 multiprocessing 多线程Threading 线程池和进程池concurrent.futures

    multiprocessing.procsess 定义一个函数 def func():pass 在if __name__=="__main__":中实例化 p = process( ...

  10. Cplex: MIP Control Callback Methods

    *本文主要记录和分享学习到的知识,算不上原创 *参考文献见链接 本文主要归纳了Cplex的Control callback常用的方法. 目录 NodeCallback SolveCallback Us ...