簡體   English   中英

三向比較運算符總是有效嗎?

[英]Is the three-way comparison operator always efficient?

Herb Sutter在他的“宇宙飛船”運營商提案 (第12.2節,第12頁底部)中說:

基於<=>及其返回類型的所有內容:此模型具有主要優勢,與之前的C ++提案和其他語言的功能相比,此提案有一些獨特之處:

[...]

(6) 效率,包括最終實現用於比較的零開銷抽象:絕大多數比較總是單通道。 在支持部分排序​​和相等的類型的情況下,唯一的例外是生成<=>= 對於< ,單次傳遞對於實現零開銷原則至關重要,以避免重復相等比較,例如對於struct Employee { string name; /*more members*/ }; struct Employee { string name; /*more members*/ }; 用於struct Outer { Employeee; /*more members*/ }; struct Outer { Employeee; /*more members*/ }; - 今天的比較違反了零開銷抽象,因為operator< on Outer執行冗余的相等比較,因為它執行if (e != that.e) return e < that.e; 它遍歷e.name的相等前綴兩次(如果名稱相等,則遍歷Employee的其他成員的相等前綴兩次),這通常無法優化。 正如Kamiński所指出的,零開銷抽象是C ++的支柱,並且首次實現它的比較是基於<=>的這種設計的一個重要優勢。

但他給出了這個例子(第1.4.5節,第6頁):

class PersonInFamilyTree { // ...
public:
  std::partial_ordering operator<=>(const PersonInFamilyTree& that) const {
    if (this->is_the_same_person_as ( that)) return partial_ordering::equivalent;
    if (this->is_transitive_child_of( that)) return partial_ordering::less;
    if (that. is_transitive_child_of(*this)) return partial_ordering::greater;
    return partial_ordering::unordered;
  }
  // ... other functions, but no other comparisons ...
};

operator>(a,b)定義a<=>b > 0不會導致較大的開銷? (雖然形式與他討論的不同)。 該代碼首先測試相等性,然后測試less ,最后測試greater ,而不是僅測試greater

我在這里錯過了什么嗎?

operator>(a,b)定義a<=>b > 0不會導致較大的開銷?

這會導致一些開銷。 然而,開銷的大小是相對的 - 在運行比較的成本相對於程序的其余部分可忽略不計的情況下,通過實現一個運算符而不是五個運算符來減少代碼重復可能是可接受的權衡。

但是,該提案並未建議刪除其他比較運算符以支持<=> :如果您想要重載其他比較運算符,您可以自由地執行此操作:

概括:不要限制固有的東西。 不要隨意限制一整套用途。 避免特殊情況和部分功能。 - 例如,本文支持所有七個比較運算符和運算,包括通過<=>添加三向比較。 它還支持所有五個主要比較類別,包括部分訂單。

對於一些大的定義。 存在開銷,因為在部分排序中, a == b iff a <= bb <= a 復雜性與拓撲排序O(V+E) 當然,現代C ++方法是編寫安全,清晰和可讀的代碼然后進行優化。 您可以先選擇實施飛船運營商,然后在確定性能瓶頸后進行專業化。

一般來說,當你處理一種類型時,重載<=>是有意義的,一次性進行所有比較要么只是比較昂貴,要么與比較它們的成本相同。

對於字符串, <=>似乎比直接==測試更昂貴,因為你必須減去每對兩個字符。 但是,由於您已經必須將每對字符加載到內存中,因此在其上添加減法是一項微不足道的費用。 實際上,比較兩個數字的相等性有時會被編譯器實現為減法和零測試。 即使對於那些不這樣做的編譯器,減法和與零進行比較也可能沒有明顯低效。

所以對於像這樣的基本類型,你或多或少都很好。

當你處理樹木訂購之類的事情時,你真的需要事先知道你關心的操作。 如果您要求的是== ,那么您真的不想要搜索樹的其余部分,只是為了知道它們是不相等的。

但是個人......我永遠不會用比較運算符來實現像樹排序這樣的東西。 為什么? 因為我認為這樣的比較應該是邏輯上快速的操作。 樹搜索是一個如此緩慢的操作,你真的不想偶然或在絕對必要的時候做任何時間。

看看這個案子吧。 說一個家譜中的人“少於”另一個人,這究竟意味着什么? 這意味着一個人是另一個人的孩子。 使用is_transitive_child_of直接問這個問題,在代碼中是不是更具可讀性?

您的比較邏輯越復雜,您所做的事實就越不可能是“比較”。 可能有一些文本描述可以調用這種“比較”操作,這種操作更具可讀性。

哦,當然,這樣的類可以有一個函數返回一個表示兩個對象之間關系的partial_order 但我不會調用該函數operator<=>

但無論如何, <=>是開銷比較的零開銷? 沒有; 您可以構建一些案例,其中計算訂單的成本要比檢測您要求的特定關系的成本高得多。 但個人如果是這樣的話,還有,你不應該通過運營商比較這些類型的好機會。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM