簡體   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