sort函数奇遇记_记一次C++使用sort函数遇到的问题

sort函数奇遇记

1.问题简述

  最近在用C++的sort函数排序vector元素时,遇到一个错误,特地在此记录一下。我将当时出错的代码抽象一下,类似于下面这种形式。

int main() {
    vector nums = { 5,8,5,6,4,7,56,8 };
    sort(nums.begin(), nums.end(), [](int a, int b) {
        return a <= b; });
    return 0;
}

  这段代码看似没任何问题,但是会遭遇到严重的运行时错误,通过测试发现,只有当比较函数为<=,且nums数组中存在重复元素时才会错误。而修改也比较简单,将lambda函数里面的<= 改为 < 即可。

2.问题剖析

  为了进一步弄清楚产生这个现象的原因,我查看了Cplusplus
上sort函数中comp参数的介绍,如下所示:

Binary function that accepts two elements in the range as arguments, and returns a value convertible to . The value returned indicates whether the element passed as first argument is considered to go before the second in the specific strict weak ordering it defines.

  由其定义可知comp参数必须基于一种定义的严格弱序来判断第一个参数是否在第二个参数之前。那么什么是严格弱序呢?其实严格弱序就是两个的对象(比如a和b)的一种关系,该关系必须满足以下特性(我们定义严格弱序关系的符号为,例如 ,即为严格弱序于):

  1. 互斥性,如果 ,那么 一定为假;
  2. 传递性,如果 ,那么一定有;
  3. 如果 都不成立,那么 a 一定等于 b;

  其实,这里我们也能猜出,sort函数的comp参数,其实是定义一个判断参数a和参数b是否严格弱序的布尔函数,如果是严格弱序则返回true,否则返回false;
  回到我们那段出错的代码,我们可以看一下lambda函数是否符号严格弱序的定义。我们可以发现,当a==b时,a<=b 和 b<= a都成立,即同时成立,这违反了互斥性原则,因此函数会参数运行时错误。弄清楚了原因,修改起来也十分简单,而且以后在写相关的sort函数的comp参数时一定要注意这一点。

3.总结
  1. 有时候用了很久没出问题的函数,不一定代表你真的熟悉了他,其实你有可能还是理解错了,只是并没有遇到能让你出错的应用场景,而一旦出错后果将不堪设想。每一次看似成功的运行,都加强了自己对其盲目的自信,进而加大了以后遇到意外状况的debug难度和隐患。
  2. (https://www.cplusplus.com)是一个宝库。
4.参考
  1. sort - C++ Reference (cplusplus.com)
  2. C++ 严格弱序_River_Lethe的博客-CSDN博客
  3. C++ stl 的sort使用中的坑_孙新的铁匠铺-CSDN博客

你可能感兴趣的:(sort函数奇遇记_记一次C++使用sort函数遇到的问题)