自定义排序函数实现时需要注意的问题
来源:互联网 发布:vb调用大漠插件 编辑:程序博客网 时间:2024/05/15 08:18
stl范型算法中的sort可以根据自定义的函数进行排序,也可以用函数对象。我今天碰到一个关于错误地定义此函数的问题,运行时出现assert异常,检查了好久以后,才发现是什么原因。
我要比较两个CPoint *类型的对象,定义的函数如下:
bool compair_points(CPoint const* p1, CPoint const* p2)
{
return p1->x-p2- >x;
}
我是要用这个函数按照每个点的x坐标的大小来排序,所以直接用减法,看起来没什么问题,于是就对一个数组排序了,但是运行时老是在sort那句出现错误,反正是说小于符号的问题。就像下面这样的信息:
Debug Assertion Failed!
Program: f:"My Cpp"mfc projects"FindCenter"debug"FindCenter.exe
File: d:"microsoft visual studio 8"vc"include"algorithm
Line: 2764
Expression: invalid operator<
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
看样子是说小于符号定义得不对。我跟踪到出现异常的stl的源代码的一个函数中,就是下面这个函数:
template<class _Pr, class _Ty1, class _Ty2> inline
bool __CLRCALL_OR_CDECL _Debug_lt_pred(_Pr _Pred, _Ty1& _Left, _Ty2& _Right,
const wchar_t *_Where, unsigned int _Line)
{ // test if _Pred(_Left, _Right) and _Pred is strict weak ordering
if (!_Pred (_Left, _Right))
return (false);
else if (_Pred(_Right, _Left))
_DEBUG_ERROR2("invalid operator<", _Where, _Line);
return (true);
}
看 了这个函数,我就知道错误了。这个函数要求对于调用的两个参数交换位置时不能得到相同的结果,其实理论上也是这样,如果a比b小,则b肯定不会比a小。如 果定义的函数既得出a比b小,又得出b比a小,那这个函数定义得肯定有问题。所以我定义的那个比较函数有问题,里面只有一句return p1->x-p2->x;显然,不管p1和p2的x为何值,只要他们的x不同,那么这个函数都回返回true,所以这样定义是错误的。应该 为:return (p1->x-p2->x)<0;
看来以后要严禁,该用逻辑类型的时候就严格地使用逻辑类型,而不要使用算数类型,否则容易出逻辑错误,这样的错误很难检查。stl的代码中对于这样的愚蠢错误进行了检查,感觉还是很人性化的,虽然提示不太明确,但是对找错很有帮助。
显然,对于比较函数,sort方法要求的只是小于符号,当然如果要降序排列也可以定义成别的,只要不出现像上面那样的冲突。定义返回值不要比 较<=或者>=,因为中间有了等于,同样会出现逻辑错误,如果a>=b,则当b==a时,b>=a也是成立的,所以同样会出错。 两个元素相等不能考虑在这个里面。实际上当两个元素相等时谁排在前面或者后面根本就不重要。如果一定要排除个顺序来,就还要根据别的条件来排,比如说,我 的这个根据x坐标来排序的函数,假设数组中没有重复的点,则当x相等时,再根据y来排序,可以这样:
bool compair_points(CPoint const* p1, CPoint const* p2)
{
if(p1->x!=p2->x)
return (p1->x-p2->x)<0;
else
return (p1->y-p2->y)<0;
}
- 自定义排序函数实现时需要注意的问题
- 自定义排序函数实现时需要注意的问题
- STL自定义排序函数 需要注意的问题
- 自定义序列化实现Externalizable接口需要注意的问题
- 自定义ruby异常时需要注意的一个问题
- linux自定义信号需要注意的问题
- 自定义View需要注意的问题
- 自定义View需要注意的问题
- 指针作为函数参数传递时需要注意的问题
- scanf()函数--需要注意的问题2
- 使用header()函数需要注意的问题
- 用异或操作实现的交换函数用以实现数组逆置中需要注意的问题
- 写正确函数需要注意的地方:快速排序
- C++学习总结_成员函数的声明和实现需要注意问题
- 需要注意的问题
- 需要注意的问题
- 使用WebService传递自定义对象需要注意的问题
- 自定义Panel中添加依赖属性需要注意的问题
- Java 异常机制
- Linux下JNI实现
- 第20届国际C语言混乱代码大赛获胜者宣布
- linux下面快速删除大量文件
- Java内部类
- 自定义排序函数实现时需要注意的问题
- struts2中拦截器使用
- 输入、输出技巧总结,常用位运算
- 应用程序徽章-IOS开发
- 打开键盘遮住View的问题解决方法-IOS开发
- 试用 Entity Framework Power Tools CTP1 [ 不用再为生成实体类发愁了 ]
- 锁定表头和列
- 状态模式
- (转)D3D-Z缓冲