在 《 C++ Templates 2nd Edition 》Chapter 1 中,作者将 max() 模板定义如下:

  

template <typename T>

T max(T a, T b)
{
return b < a ? a : b; // 而不是 return a < b ? b : a;
}

  同时在书下注释里,作者写道 :“Note that the max() template according to [StepanovNotes] intentionally returns “b < a ? a : b” instead of “a < b ? b : a” to ensure that the function behaves correctly even if the two values are equivalent but not equal. ”

  翻译过来就是 : 根据 [StepanovNotes] 故意写成这样的, 为的就是,当两个值 ' equivalent ' 但不 ' equal ' 的时候函数也能表现正常

  但这个 equivalent 但不 equal ,让人很难理解。

  cppreference 上说,For the types that are both EqualityComparable and LessThanComparable, the C++ standard library makes a distinction between equality, which is the value of the expression a == b and equivalence, which is the value of the expression !(a < b) && !(b < a).

  意思就是:

  1.   满足 !(a < b) && !(b < a) 的时候, a 和 b 是 equivalent 的, 因为 a 不小于 b 而且 b 不小于 a。两个变量是否是 equivalence ,由 operator< 决定。
  2.   满足 a == b 的时候, a 和 b 是 equal 的, 因为 a 等于 b。 两个变量是否是 equal,由 operator== 决定。

  



  回到开头,为何要写成  return b < a ? a : b; 呢?

  看下面这个例子:

    int x = , y = ;
const int& max = std::max(x, y);
const int& min = std::min(x, y);
std::cout
<< "std::min(x, y)" << std::endl
<< "x :\t" << &x << std::endl
<< "y :\t" << &y << std::endl
<< "max :\t" << &max << std::endl
<< "min :\t" << &min << std::endl;

  对 std::max(x, y) 和 std::min(x, y) 的结果进行引用时,返回的都是 x。

  这只是基本数据类型,只要 !(a < b) && !(b < a) 就可以认为是 a == b,虽然他们的地址不同。这和在Python里 a == b 和 a is b 的区别异曲同工。但若是对自定义数据类型这么搞,就可能完蛋,因为operator< 和 operator== 的判断标准不一定相同。

  比如 :

 

struct 学生
{
int 成绩;
string 名字;
string 学号;
bool operator<(学生 乙)
{
return this->成绩 < 乙.成绩;
} bool operator==(学生 甲, 学生 乙)
{
return 甲.学号 == 乙.学号;
}
} int main()
{
std::array<学生, > 成绩排序( min(甲, 乙), max(甲, 乙) );
}

  如果 max 和 min 返回的都是甲,就完蛋了,给成绩排序居然把乙给搞没了。而这也就是 std::min() 和 std::max() 会导致的问题。

  

知乎问题: https://www.zhihu.com/question/266917342

stackoverflow : https://stackoverflow.com/questions/31974941/what-is-the-difference-between-equivalence-and-equality

为什么 max() 应该写成 b < a ? a : b 呢?的更多相关文章

  1. Python爬虫小实践:寻找失踪人口,爬取失踪儿童信息并写成csv文件,方便存入数据库

    前两天有人私信我,让我爬这个网站,http://bbs.baobeihuijia.com/forum-191-1.html上的失踪儿童信息,准备根据失踪儿童的失踪时的地理位置来更好的寻找失踪儿童,这种 ...

  2. CSS Icon 项目地址 小图标-用css写成的

    http://cssicon.space/#/icon/focus 这是所有用css写成的  小图标  右侧有 html和css代码

  3. HTML 5 背离贪吃蛇 写成了类似于屏幕校准

    中间写了改 改了写 还是没做出自己满意的效果 ,看来自己的确不是一个走前端的料子.当然h5还是学一点好一点 具体说来 就是 在canvas 的画布中 鼠标点击后画上一个圆形 然后就有随机的在画布上面出 ...

  4. ASP.NET的一次奇遇:UserControl写成Control引发的w3wp进程崩溃

    昨天在写代码中一不小心将UserControl写成了Control,将原来应该继承自System.Web.UI.UserControl的用户控件,比如下面的BlogStats: <%@ Cont ...

  5. Excel日期格式单元格写成yyyy.MM.dd格式将无法读取到DataTable

    最近在改公司的订单系统,遇到了一个奇怪的问题.C#程序需要从Excel文件中将数据全部读取到DataTable,其中Excel文件的第一列是日期格式yyyy/MM/dd,而这一列中大部分的单元格都是按 ...

  6. 使用gfortran将数据写成Grads格式的代码示例

    使用gfortran将数据写成Grads格式的代码示例: !-----'Fortran4Grads.f90' program Fortran4Grads implicit none integer,p ...

  7. 刺猬大作战(游戏引擎用Free Pascal写成,GUI用C++写成,使用SDL和Qt4)

    游戏特性[编辑] 游戏引擎用Free Pascal写成,GUI用C++写成,使用SDL和Qt4[2]. 0.9.12开始支持实时动态缩放游戏画面. 个性化[编辑] 刺猬大作战有着高度定制性 游戏模式: ...

  8. Selenium爬取电影网页写成csv文件

    绪论 首先写这个文章的时候仅仅花了2个晚上(我是菜鸟所以很慢),自己之前略懂selenium,但是不是很懂csv,这次相当于练手了. 第一章 环境介绍 具体实验环境 系统 Windows10教育版 1 ...

  9. indexOf刚开始写成IndexOf出错

    {{# if(d.fronturlmin ==null||d.fronturlmin ==""){ }} <img src="@System.Configurati ...

随机推荐

  1. Go语言的跳跃表(SkipList)实现

    之所以会有这篇文章,是因为我在学习Go语言跳表代码实现的过程中,产生过一些困惑,但网上的大家都不喜欢写注释- - 我的代码注释一向是写的很全的,所以发出来供后来者学习参考. 本文假设你已经理解了跳表的 ...

  2. Python操作adb命令脚本

    一.脚本代码(有错误,抓紧改进中) import os import datetime date1=datetime.datetime.now().strftime('%Y%m%d') date2=d ...

  3. pandas之groupby分组与pivot_table透视

    一.groupby 类似excel的数据透视表,一般是按照行进行分组,使用方法如下. df.groupby(by=None, axis=0, level=None, as_index=True, so ...

  4. OnePill本地保存用户的结构

    sharedPreferences存储的数据 int Code code 表示当前用户的类别:医生为1,用户为2. Sting user user 存储当前user的json字符串 String do ...

  5. IO—》打印流&commons-IO

    打印流 打印流添加输出数据的功能,使它们能够方便地打印各种数据值表示形式. 打印流根据流的分类: 字节打印流 PrintStream 字符打印流 PrintWriter 方法: void print( ...

  6. NanoHTTPD服务

    需要导入nanohttpd2.3,jar包 继承NanoHTTPD public class HttpServer extends NanoHTTPD { public HttpServer(int ...

  7. phpcms根据二级栏目列表写的三级栏目列表

    <div class="container"> <!--左边树状导航--> <div class="CNLTreeMenu" id ...

  8. webpack 4.x版本手动配置

    运行 npm init -y 快速初始化项目 在项目根目录创建src源代码目录和dist产品目录 在src目录下创建 index.html mani.js文件如果后期使用entry打包,这里可以手动创 ...

  9. 《谁说菜鸟不会数据分析》高清PDF全彩版|百度网盘免费下载|Python数据分析

    <谁说菜鸟不会数据分析>高清PDF全彩版|百度网盘免费下载|Python数据分析 提取码:p7uo 内容简介 <谁说菜鸟不会数据分析(全彩)>内容简介:很多人看到数据分析就望而 ...

  10. cpp求职

    //Created by Arc on 2020/5/23 //////// Created by snnnow on 2020/5/20.//////面向对象的程序设计-期中测试// 根据题目实现求 ...