这两天忙着在准备3月份打PAT考试,许久没有接触刷题了,各种生疏各种忘记,刷题速度那是一个慢,真是为自己智商着急。今天刷题碰到了一个有意思的编程习惯性错误,好几道题都涉及到自定义排序,需要自己重写<操作符号,我在调试的时候,程序提示assertion error: Invalid operator<,思考了很久也没有发现问题,在网上搜寻了这个问题,大概是理解了,将我对这个问题的理解总结一下。

案例:如自定义结构体Cmp

 struct Cmp
{
int field1,field2;
bool operator<(const Cmp& cmp)
{
if(this->field1 < cmp.field1) return true;
else if(this->field2 < cmp.field2) return true;
return false;
}
};

此结构体的大小主要是按照field1进行排列,如果field1排不出来,就按照field2进行排列。这段代码看上去没有什么问题,但是如果使用algorithm stl中的sort函数对含有此类型的数组进行排序,在debug模式下会出现断言失败的提示,即invalid operator<,表示这个自定义的比较函数不严格,可能会有问题。

仔细分析,也很容易看出来这段代码错在什么地方,在第二个if判断中,我们仅仅是判断了第二个field大小,忘记加上对第一个field的限制了,把该if判断改成

else if(this->field2 < cmp.field2 && this->field1 == cmp.field1)

发现警告消失了,为什么会这样呢?标准库中的sort函数为什么要我们这么写?

sort函数要求比较函数是strict weak ordering的,而strict weak ordering必须满足三个条件:

1) Strict: pred (X, X) is always false.  X跟X自己比为false

2) Weak: If ! pred (X, Y) && !pred (Y, X), X==Y. 当X<Y和Y<X都不成立时,X等于Y

3)Ordering: If pred (X, Y) && pred (Y, Z), then pred (X, Z). 当X<Y,Y<Z时,X<Z成立,即排序的一个传递性。

用一个实例来说明问题。假设有三个变量,m1(1,2),m2(2,1),m3(1,2)。(括号内的两个数分别表示field1和field2的值。在前面有问题的代码下,我们可以判断:

1)m1<m2,并且m2<m3,根据条件3,m1<m3,但是很明显m1跟m3是一样的,应该是相等的!

2)也可以发现在该规则下,m2<m1也成立!根据条件1,推导出m1竟然与m2相等,m1==m2!

这两个情况明显不符合常理,如果允许程序这样运行,最后的结果谁也想不到会排成什么样子。

综上所述,在写比较函数的时候一定要小心,不要粗心大意漏掉了条件。这也告诫了我们编译器给出的各种提示警告,还是老老实实地去遵守比较好,不然到后来吃了哑巴亏也不知道是什么地方出了问题。

Invalid operator< assertion error解析的更多相关文章

  1. python_paramiko_SSHException Invalid requirement, parse error at

    不加sleep(0.5)会出现SSHException: Invalid requirement, parse error at " '' "问题,原因暂时未知. 结论如下 如果不 ...

  2. STL sort “invalid operator <”

    跟踪了下,是比较函数(下面的_Pred)的问题: template<class _Pr, class _Ty1, class _Ty2> inline bool _Debug_lt_pre ...

  3. c++中sort函数调用报错Expression : invalid operator <的内部原理 及解决办法

    转自:https://www.cnblogs.com/huoyao/p/4248925.html 当我们调用sort函数进行排序时,中的比较函数如果写成如下 bool cmp(const int &a ...

  4. c++中sort函数调用报错Expression : invalid operator <的内部原理

    当我们调用sort函数进行排序时,中的比较函数如果写成如下 bool cmp(const int &a, const int &b) { if(a!=b) return a<b; ...

  5. Spark in action on Kubernetes - Spark Operator的原理解析

    前言 在上篇文章中,向大家介绍了如何使用Spark Operator在kubernetes集群上面提交一个计算作业.今天我们会继续使用上篇文章中搭建的Playground进行调试与解析,帮助大家更深入 ...

  6. 解决Linux下编译.sh文件报错 unexpected operator Syntax error: word unexpected

    执行一个脚本  发现报语法错误,但是在其他机器上运行都没有问题 唯一的区别就是 一个是centos机器  报错的是ubuntu 网上搜索了一下 因为Ubuntu默认的sh是连接到dash的,又因为da ...

  7. 问题:编译eshoponcontainers失败,提示error:invalid reference format

    环境: visual studio 2017 v15.4.2,docker ce Version 17.06.0-ce-win19 (12801) 参考问题页: https://github.com/ ...

  8. “Debug Assertion” Runtime Error on VS2008 VS2010 winhand.cpp

    I'm writing a C++ MFC program on VS2008 and I'm getting this "Debug Assertion Error" when ...

  9. System Error Codes

    很明显,以下的文字来自微软MSDN 链接http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx M ...

随机推荐

  1. MySql中报错:java.sql.SQLException: Incorrect string value: '\xF0\x9F\x90\xBB' for column

    问题描述: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x90\xBB' for column 'nickName' at row ...

  2. 3D Computer Grapihcs Using OpenGL - 07 Passing Data from Vertex to Fragment Shader

    上节的最后我们实现了两个绿色的三角形,而绿色是直接在Fragment Shader中指定的. 这节我们将为这两个三角形进行更加自由的着色——五个顶点各自使用不同的颜色. 要实现这个目的,我们分两步进行 ...

  3. 学习日记18、easyui 文件框上传文件

    前台 <tr> <td style="width:100px; text-align:right;"> @Html.LabelFor(model => ...

  4. httpscan 爬虫式的网段Web主机发现小工具

    httpscan是一个扫描指定网段的Web主机的小工具.和端口扫描器不一样,httpscan是以爬虫的方式进行Web主机发现,因此相对来说不容易被防火墙拦截.httpscan会返回IP http状态码 ...

  5. 2018-2019-2 20175214 实验三《敏捷开发与XP实践》实验报告

    一.实验内容 1.编码标准:在IDEA中使用工具(Code->Reformate Code)把下面代码重新格式化,再研究一下Code菜单,找出一项让自己感觉最好用的功能.提交截图,加上自己学号水 ...

  6. lazyload懒加载插件

    在main.js中引入vue-lazyload插件  并使用 注册插件: import VueLazyLoad from 'vue-lazyload' Vue.use(VueLazyLoad,{ lo ...

  7. Jenkins简介&邮箱配置

    一.Jenkins基本介绍: Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能.--摘自百科 二 ...

  8. Java Bean 使用包装类型 还是基本类型

    参考:实体类中用基本类型好,还是用包装类型好_ - 牵牛花 - 博客园 int优缺点 优点: 1.用于Bean的时候,有默认值.比如自己拼接sql增加一个User时,会方便很多,不过现在都用ORM框架 ...

  9. vue组件兄弟间通信

    四.兄弟组件间通信(event) 借助于一个公共的Vue的实例对象,不同的组件可以通过该对象完成事件的绑定和触发 var bus = new Vue(); bus.$emit()bus.$on() 熊 ...

  10. 【MM系列】SAP MM-模块物料主数据简介

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP MM-模块物料主数据简介   ...