[英]C++ STL - How does the third argument of the STL sort() work?
我希望根據其數據成員' age
'對class Person
的對象數組進行排序。 我將對象存儲在vector<Person> v
。
據我所知,至少有4種方法可以執行此操作,我根據下面的方法提出以下問題。
如何在類中定義operator()
工作? 我不應該在這里重載“<”運算符嗎? 為什么'()'?
我在方法1中發送了一個對象作為第3個參數。但是,在方法2中,我發送了一個函數的名稱。 為什么會那樣?
四種方法中哪一種最好? 我覺得方法3是最簡單的。
方法1
class cmp
{
public:
bool operator() ( Person const &a, Person const &b )
{
return a.age < b.age ;
}
};
sort( v.begin(), v.end(), cmp());
方法2
bool cmp( const Person a, const Person b )
{
return a.age < b.age ;
}
sort( v.begin(), v.end(), cmp );
方法3
bool operator < ( const Person a, const Person b )
{
return a.age < b.age ;
}
sort( v.begin(), v.end());
方法4
//using lambda expression
sort( v.begin(), v.end(), [](const Person &a, const Person &b){return a.age < b.age;});
要使用std::sort
(或任何函數)對范圍進行std::sort
,它需要知道如何比較范圍中的兩個元素,以確定小於(或大於)的關系。
標准庫函數std::sort
有兩種形式 :一種使用operator<
,另一種使用compare函數/ functor。 您已經在代碼中使用了它們 - 特別是,示例中的第三個使用<
,其余使用比較函數/仿函數。
至於哪一個是最好的方法?
這要看情況。 使用operator<
那個不太靈活,因為它是固定的,但也需要你少輸入。 當它足夠時使用它。
另一個更靈活,因為您可以傳遞任何比較功能並相應地對您的元素進行排序。 當operator<
不夠時使用它。 此外,當你選擇這種風格時,你還有其他選擇:比較器可以是函數 , 函子或lambda - 如果你使用函數或函子(在命名空間級別定義),那么你可以重用它們; 另一方面,lambda 通常在函數范圍內定義,因此它不是可重用的,除非你在命名空間范圍內定義它,在這種情況下它幾乎與函數相同。
例如,假設您要按遞增順序對int
的向量進行排序:
std::vector<int> v{10, 3, 12, -26};
std::sort(v.begin(), v.end());
print(v);
產量: -26,3,10,12
。 所以operator<
確實做到了。
但是如果你想要僅考慮幅度 (即忽略符號)排序的元素,那么你必須使用另一種風格:
std::vector<int> v{10, 3, 12, -26};
auto abs_cmp = [](int a, int b) { return std::abs(a) < std::abs(b); };
std::sort(v.begin(), v.end(), abs_cmp);
print(v);
輸出: 3,10,12,-26
。 這是您在這種情況下期望的輸出。
希望有所幫助。
sort函數有兩個重載
一世。 void sort( RandomIt first, RandomIt last );
它不接受比較函數,它期望項目具有operator<
定義的operator<
。 你的方法3使用這個重載。
template< class RandomIt >
void sort( RandomIt first, RandomIt last )
{
...
if (*i < *j)
....
...
}
II。 void sort( RandomIt first, RandomIt last, Compare comp );
它接受比較功能,當你的物品沒有operator<
定義的operator<
時,它很有用。
template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp )
{
...
if (comp(*i, *j))
....
...
}
方法1,2,4使用此重載。 所有傳遞的第三個參數都可以通過()
調用。 方法1,通過cmp()
發送一個對象,這個對象有重載的operator()
和上面的代碼調用它。 方法2和4,發送指向函數的指針,指向函數的指針可以由()
調用。
如何在類中定義operator()工作? 我不應該在這里重載“<”運算符嗎? 為什么'()'?
operator()
是函數調用運算符。 類cmp
實例可以與函數可調用的方式相同的方式調用。 sort
需要調用以執行必要的比較。
我在方法1中發送了一個對象作為第3個參數。但是,在方法2中,我發送了一個函數的名稱。 為什么會那樣?
cmp
實例是可調用的。 函數名稱是可調用的。
四種方法中哪一種最好? 我覺得方法3是最簡單的。
3的主要缺點是你已經根據他們的年齡定義了一個人小於或大於另一個人。 如果你想在其他地方按名稱排序怎么辦? 您已經定義了operator<
for Person,因此您無法再次執行相同的操作。 所有其他三種方法都定義了在特定排序中使用的比較,而不是定義比較Person
一般含義。
2的主要缺點是編譯器內聯比1或4更難。它沒有超過1的任何優點,但為了完整性, sort
可以采用函數指針。
4的主要優點是,如果你只使用一次比較,那么在調用sort
的同一行代碼中將它放在那里通常更好,而不是在文件的其他地方。
1的主要優點是它適用於C ++ 03(與4不同)。 4或多或少是1的新語法.1還具有使比較器可用於其他代碼以使用相同名稱的優點。 如果你想要的話,你也可以用lambda來實現(通過將lambda命名為auto
變量來命名lambda)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.