繁体   English   中英

std :: sort with custom comparator

[英]std::sort with custom comparator

在下面的代码中,为什么所有三个IntComparator()IntComparator2IntComparator3都作为sort()函数的第三个参数? 他们不会有不同的l值函数类型吗? 基于https://en.cppreference.com/w/cpp/algorithm/sort,它说

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

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

哪个似乎更符合IntComparator2

还有哪一个更好? 第三种选择似乎更简单,更直观。


#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

struct IntComparator
{
  bool operator()(const int &a, const int &b) const
  {
    return a < b;
  }
};

bool IntComparator2 (const int &a, const int &b)
{
    return a < b;
}

bool IntComparator3 (int a, int b)
{
    return a < b;
}

int main()
{
    int items[] = { 4, 3, 1, 2 };
    std::sort(items, items+4, IntComparator());

    for (int n=0; n<4; n++) {
        std::cout << items[n] << ", ";
    }

    std::cout << "\n";

    int items2[] = { 4, 3, 1, 2 };
    std::sort(items2, items2+4, IntComparator2);

    for (int n=0; n<4; n++) {
        std::cout << items2[n] << ", ";
    }

    std::cout << "\n";

    int items3[] = { 4, 3, 1, 2 };
    std::sort(items3, items3+4, IntComparator3);

    for (int n=0; n<4; n++) {
        std::cout << items3[n] << ", ";
    }

    std::cout << "\n";

    return 0;
}

std::sort接受一个functor 这是可以调用的任何对象(使用正确的参数)。 该功能通过使用模板实现此目的,如下所示

template<typename Iter, typename Comp>
void sort(Iter begin, Iter end, Comp compare) { ... }

IntComparator1和3都是这个比较器的有效函子,因为它们都可以使用带有2个整数的operator()来调用。

也像你说的那样,第三种选择确实通常更直观。

sort()函数只需调用您在需要比较时提供的比较器函数。 比较器获取其参数(value,reference,const ref)的方式不是sort()的关注点,无论比较器如何在内部获取其参数,它都将以相同的方式调用它(传递两个相同类型的参数)。
从比较器定义之外看不到它,因为我们称之为三个函数的方式完全相同。

唯一要求的是比较器只接受两个参数,它们必须是要排序的元素的相同类型。

但是,通过const ref更好是因为你的比较器保证不修改它比较的参数,并且它避免了无用的副本(性能增益)。 这就是为什么他们写的应该是等价的 (不同的必须是等价的 )。

它们是等价的,因为C ++规范说它们都符合二元谓词的要求。 以下摘录似乎相关。

[function.objects]

20.14.1函数对象类型是一种对象类型,它可以是函数调用中的postfix-expression的类型([expr.call],[over.match.call])。224函数对象是一个对象。功能对象类型。 在人们期望将指向函数的指针传递给算法模板的地方,指定接口接受函数对象。 这不仅使算法模板与函数指针一起使用,而且使它们能够使用任意函数对象。

[alg.sorting]

25.7.2 Compare是一个函数对象类型([function.objects]),它满足名为BinaryPredicate([algorithms.requirements])的模板参数的要求 当上下文转换为bool([conv])时,应用于Compare类型的对象的函数调用操作的返回值,如果调用的第一个参数小于第二个参数,则返回true,否则返回false。 比较comp用于假设有序关系的算法。

[algorithms.requirements]

25.2.8如果没有其他约束,只要算法需要一个函数对象,当应用于取消引用两个相应迭代器的结果或解除引用迭代器并且当T是签名的一部分时键入T,则返回值testable时使用BinaryPredicate参数是的。 换句话说,如果算法将BinaryPredicate binary_pred作为其参数,并将first1和first2作为其迭代器参数以及相应的值类型T1和T2,则它应该在构造binary_pred(* first1,* first2)中正确转换为bool([ CONV])。 除非另有说明,否则BinaryPredicate总是将第一个迭代器的value_type作为其第一个参数,也就是说,在T值是签名的一部分的情况下,它应该在构造binary_pred(* first1,value)中正确地在上下文中转换为bool( [CONV])。 binary_pred不应通过解除引用的迭代器应用任何非常量函数。 给定一个glvalue u类型(可能是const)T1指定与* first1相同的对象,glvalue v指定类型(可能是const)T2指定与* first2相同的对象,binary_pred(u,* first2),binary_pred( * first1,v)和binary_pred(u,v)应各自是一个等于binary_pred(* first1,* first2)的有效表达式,而binary_pred(u,value)应该是一个等于binary_pred的有效表达式( * first1,value)。

至于哪个更好的问题,我会说这是基于意见的,除非在你的具体情况下,分析表明一个更好。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM