在 《 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. ES数据库搜索

    1.倒排索引 1.倒排索引和正向索引 在全文搜索里,文档数据离不开搜索,而搜索离不开索引(没有索引搜索会很低效),倒排索引(Inverted index)是全文搜索系统里最高效的索引方法和数据结构,E ...

  2. PHP 中的字符串变量

    PHP 字符串变量 字符串变量用于存储并处理文本. PHP 中的字符串变量 字符串变量用于包含有字符的值. 在创建字符串之后,我们就可以对它进行操作了.您可以直接在函数中使用字符串,或者把它存储在变量 ...

  3. PHP next() 函数

    实例 输出数组中的当前元素和下一个元素的值: <?php$people = array("Peter", "Joe", "Glenn" ...

  4. PHP tanh() 函数

    实例 返回不同数的双曲正切: <?php高佣联盟 www.cgewang.comecho(tanh(M_PI_4) . "<br>");echo(tanh(0.5 ...

  5. luogu P2607 [ZJOI2008]骑士 tarjan dp

    LINK:骑士 本来是不打算写的 发现这道题在tarjan的时候有一个坑点 所以写出来记录一下. 可以发现图可能是不连通的 且一个连通块中是一个奇环树. 做法:类似tarjan找割点 然后把环给拉出来 ...

  6. Hadoop学习之TextInputFormat分片逻辑探究

    期望 顺着上一篇文章<Hadoop学习之第一个MapReduce程序>中遗留的分片疑惑,探究TextInputFormat的分片逻辑. 第一步 上Apache官网下载实验所使用的Hadoo ...

  7. 阿里云Redis的开发规范

    作者:付磊-起扬 来源:https://yq.aliyun.com/articles/531067 本文主要介绍在使用阿里云Redis的开发规范,从下面几个方面进行说明. 键值设计 命令使用 客户端使 ...

  8. Centos7 如何通过win10 的远程桌面连接进行远程访问

    首先,如果安装测centos7是已经安装了GNOME 或者 KDE 桌面, 则只需要再安装xrdp就可以了. 直接通过yum install xrdp 是不行的,因为xrdp 不在默认源中   先配置 ...

  9. requests上传文件,又要上传data的处理

    前话 最近在自己学着弄接口自动化框架,因为要封装一个发送请求的父类,其中有考虑到上传文件,以及同时上传文件,和传递其他字段数据,遇到点小问题 这里解决下. 实例的接口数据 参考文档 来自fastapi ...

  10. 分类模型的F1-score、Precision和Recall 计算过程

    分类模型的F1分值.Precision和Recall 计算过程 引入 通常,我们在评价classifier的性能时使用的是accuracy 考虑在多类分类的背景下 accuracy = (分类正确的样 ...