为什么 max() 应该写成 b < a ? a : b 呢?
在 《 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).
意思就是:
- 满足 !(a < b) && !(b < a) 的时候, a 和 b 是 equivalent 的, 因为 a 不小于 b 而且 b 不小于 a。两个变量是否是 equivalence ,由 operator< 决定。
- 满足 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 呢?的更多相关文章
- Python爬虫小实践:寻找失踪人口,爬取失踪儿童信息并写成csv文件,方便存入数据库
前两天有人私信我,让我爬这个网站,http://bbs.baobeihuijia.com/forum-191-1.html上的失踪儿童信息,准备根据失踪儿童的失踪时的地理位置来更好的寻找失踪儿童,这种 ...
- CSS Icon 项目地址 小图标-用css写成的
http://cssicon.space/#/icon/focus 这是所有用css写成的 小图标 右侧有 html和css代码
- HTML 5 背离贪吃蛇 写成了类似于屏幕校准
中间写了改 改了写 还是没做出自己满意的效果 ,看来自己的确不是一个走前端的料子.当然h5还是学一点好一点 具体说来 就是 在canvas 的画布中 鼠标点击后画上一个圆形 然后就有随机的在画布上面出 ...
- ASP.NET的一次奇遇:UserControl写成Control引发的w3wp进程崩溃
昨天在写代码中一不小心将UserControl写成了Control,将原来应该继承自System.Web.UI.UserControl的用户控件,比如下面的BlogStats: <%@ Cont ...
- Excel日期格式单元格写成yyyy.MM.dd格式将无法读取到DataTable
最近在改公司的订单系统,遇到了一个奇怪的问题.C#程序需要从Excel文件中将数据全部读取到DataTable,其中Excel文件的第一列是日期格式yyyy/MM/dd,而这一列中大部分的单元格都是按 ...
- 使用gfortran将数据写成Grads格式的代码示例
使用gfortran将数据写成Grads格式的代码示例: !-----'Fortran4Grads.f90' program Fortran4Grads implicit none integer,p ...
- 刺猬大作战(游戏引擎用Free Pascal写成,GUI用C++写成,使用SDL和Qt4)
游戏特性[编辑] 游戏引擎用Free Pascal写成,GUI用C++写成,使用SDL和Qt4[2]. 0.9.12开始支持实时动态缩放游戏画面. 个性化[编辑] 刺猬大作战有着高度定制性 游戏模式: ...
- Selenium爬取电影网页写成csv文件
绪论 首先写这个文章的时候仅仅花了2个晚上(我是菜鸟所以很慢),自己之前略懂selenium,但是不是很懂csv,这次相当于练手了. 第一章 环境介绍 具体实验环境 系统 Windows10教育版 1 ...
- indexOf刚开始写成IndexOf出错
{{# if(d.fronturlmin ==null||d.fronturlmin ==""){ }} <img src="@System.Configurati ...
随机推荐
- Bug--Tomcat Error start child
添加Quartz之后报错 下面的Cause by: More than one fragment with the name [spring_web] was found. This is not l ...
- 将"089,0760,009"变为 89,760,9
remove_zeros = lambda s: ','.join(map(lambda sub: str(int(sub)), s.split(','))) remove_zeros("0 ...
- abs,all,any函数的使用
''' abs函数:如果参数为实数,则返回绝对值 如果参数为复数,则返回复数的模 ''' a = 6 b = -6 c = 0 # print("a = {0} , b = {1} , c ...
- html实现a元素href的URL链接自动刷新或新窗口打开
有时我们想实现这样一个功能,点击一个链接,如果这个链接浏览器已经打开过,则刷新已经打开的链接窗口:如果这个链接没有打开过,则使用新窗口打开这个链接页面. 这是一个非常好的体验增强功能,可以有效避免浏览 ...
- C/C++编程笔记:C++入门知识丨函数和函数模板
本篇要学习的内容和知识结构概览 函数的参数及其传递方式 1. 函数参数传递方式 传值: 传变量值: 将实参内存中的内容拷贝一份给形参, 两者是不同的两块内存 传地址值: 将实参所对应的内存空间的地址值 ...
- 4.9 省选模拟赛 圆圈游戏 树形dp set优化建图
由于圆不存在相交的关系 所以包容关系形成了树的形态 其实是一个森林 不过加一个0点 就变成了树. 考虑对于每个圆都求出最近的包容它的点 即他的父亲.然后树形dp即可.暴力建图n^2. const in ...
- luogu P3217 [HNOI2011]数矩形
LINK:数矩形 题意:给出n个点 求出一个最大的矩形. 矩形可以使斜着的.(不会告诉你样例我算了几年 这道题的一个潜规则 矩形面积都是整数 我也不知道为啥一定是整数 姑且是题目输出的要求吧. 所以用 ...
- Spring的事务抽象
Spring提供了一致的事务管理抽象,该抽象能实现为不同的事务API提供一致的编程模型.无视我们使用jdbc.hibernate.mybatis哪种方式来操作数据,无视事务是jta事务还是jdbc事务 ...
- 关于innerHtml= 与 html() 区别
今天遇到的问题:如果写入的html 有<script>,必须用JQuery 的 html() 才能识别: 使用innerHtml 无法识别<script> 原因机制:待查询
- Java线程生命周期与状态切换
前提 最近有点懒散,没什么比较有深度的产出.刚好想重新研读一下JUC线程池的源码实现,在此之前先深入了解一下Java中的线程实现,包括线程的生命周期.状态切换以及线程的上下文切换等等.编写本文的时候, ...