为什么 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 ...
随机推荐
- 教孩子学编程 python语言版PDF高清完整版免费下载|百度云盘|Python入门
百度云盘:教孩子学编程 python语言版PDF高清完整版免费下载 提取码:mnma 内容简介 本书属于no starch的经典系列之一,英文版在美国受到读者欢迎.本书全彩印刷,寓教于乐,易于学习:读 ...
- BUUCTF-web EasySearch (服务端包含注入ssi)
一打开就是登录页面 存在index.php.swp...(反正我是没有扫出来,题目没给提示),分析一波源码 <?php ob_start(); function get_hash(){ $cha ...
- 轻松应对并发问题,Newbe.Claptrap 框架中 State 和 Event 应该如何理解?
Newbe.Claptrap 框架中 State 和 Event 应该如何理解?最近整理了一下项目的术语表.今天就谈谈什么是 Event 和 State. Newbe.Claptrap 是一个用于轻松 ...
- 蜻蜓点水说说Redis的String的奥秘
本篇博客参考:掘金Redis小册 敖丙 如果面试官问你,单线程的Redis为什么那么快,你可能脱口而出,因为单线程,避免上下文切换:因为基于内存,比硬盘读写快很多:因为采用的是多路复用网络模型.不管你 ...
- 虚拟机 NAT 网络静态ip配置记录
环境 VMware 15.5.5 build-16285975 centos7 虚拟网络编辑器配置 位置 编辑 --> 虚拟网络编辑器 示例 以下以 192.168.18.0 网段ip为例,实际 ...
- Django开发之Datetime类型JSON序列化时报错
前提回顾 在进行django开发view视图时,如果数据库字段是 datetime类型,在JSON序列化返回时,会出现异常 异常现象 TypeError: Object of type datetim ...
- PHP array_diff_ukey() 函数
实例 比较两个数组的键名(使用用户自定义函数比较键名),并返回差集: <?phpfunction myfunction($a,$b){if ($a===$b){return 0;}return ...
- Python time strftime()方法
描述 Python time strftime() 函数接收以时间元组,并返回以可读字符串表示的当地时间,格式由参数format决定.高佣联盟 www.cgewang.com 语法 strftime( ...
- PHP empty() 函数
empty() 函数用于检查一个变量是否为空.高佣联盟 www.cgewang.com empty() 判断一个变量是否被认为是空的.当一个变量并不存在,或者它的值等同于 FALSE,那么它会被认为不 ...
- PHP log1p() 函数
实例 返回不同数的 log(1+number): <?phpecho(log1p(2.7183) . "<br>");echo(log1p(2) . " ...