首页 > 解决方案 > 为什么 std::stable_sort() 的比较器函数的参数必须设置为常量?

问题描述

各位程序员大家好,我正在解决一个需要以稳定顺序排序的 leetcode 问题。

问题链接:https ://leetcode.com/problems/rearrange-words-in-a-sentence/submissions/

我注意到 std::stable_sort() 的比较器函数的参数必须设置为常量,否则会生成以下编译时错误。

下面是生成编译时错误的代码:

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

void display(vector<string> &a);
bool compare(string &s1, string &s2);

int main() {
    vector<string> a = {"abc", "defgh", "ijk"};

    // sorting vector<string> in stable order
    // error will be generated
    std::stable_sort(a.begin(), a.end(), compare);
    display(a);
    return 0;
}

// argument strings should be made constants???
bool compare(string &s1, string &s2) {
    return s1.length() < s2.length();
}

void display(vector<string> &a) {
    for(int i=0; i<=a.size()-1; i++) {
        cout << a[i] << " ";
    }
    cout << "\n";
    return ;
}

// errors generated
/*
    error: binding reference of type ‘std::__cxx11::basic_string<char>&’ to ‘const 
    std::__cxx11::basic_string<char>’ discards qualifiers
    177 |  { return bool(_M_comp(*__it, __val)); }

    error: binding reference of type ‘std::__cxx11::basic_string<char>&’ to ‘const 
    std::__cxx11::basic_string<char>’ discards qualifiers
    215 |  { return bool(_M_comp(__val, *__it)); }
*/

我尝试谷歌搜索,但找不到任何东西。我搜索了 Stack Overflow 并遇到了一个问题,但无法理解那里解释的原因。

堆栈溢出答案链接:

https://stackoverflow.com/a/45905608/13331053

任何帮助表示赞赏。提前致谢!

标签: c++sortingdebugging

解决方案


因为这就是函数所需要的。从 cppreference 引用std::stable_sort(强调我的):

比较函数的签名应该等同于以下内容:

bool cmp(const Type1 &a, const Type2 &b); 

虽然签名不需要const &,但函数不得修改传递给它的对象,并且必须能够接受所有类型的值(可能)const并且Type1无论Type2值类别如何(因此,Type1 &不允许[,也Type1不允许Type1move 等价于副本 (C++11 起)])。

您的函数必须接受const参数,并且非常量引用类型不符合此要求。因此,您的compare函数应如下所示:

bool compare(const string &s1, const string &s2);

GCC 完全可以接受非常量版本std::sorthttps ://godbolt.org/z/S2tL44 ,尽管它的std::sort要求与std::stable_sort. 我假设它根本没有在任何地方检查,并且std::sort实现不依赖于常量,但std::stable_sort确实如此。为什么?这将是源代码(或标准库维护者)的问题。

const&在任何情况下,始终在此类函数中使用参数以让编译器捕获对对象的任何意外修改并确保它适用于每个编译器,这将更安全、更便携。


推荐阅读