2016-06-28 240 views
3

在爲map中的自定義鍵重載operator<時,爲什麼參數和函數類型都需要conststd :: map中的自定義鍵,重載<運算符

+0

const引用表示沒有額外的參數副本,並且不能意外地在比較函數內部更改它們 – KIIV

+0

要比較兩個常量鍵,您需要兩個常量,每個參數一個。 –

+0

函數後面的'const'意味着該函數不會修改正在進行比較的對象 – smac89

回答

1

std::map<K, V>的value_type不是您想象的std::pair<K, V>,而是實際std::pair<const K, V>因此,在鍵上調用的任何比較都會處理const對象。

現在,當編譯器看到

a < b 

a至少一個或b是用戶定義類型的,編譯器調用任一

operator < (a, b); //(1) 

a.operator < (b); //(2) 

(如果這兩個都可用,則出現錯誤d)。

一個非常量成員函數,包括任何運算符,可以在非常量對象上調用只有。因此,因爲a是不變的,所以要求在//2的情況下將該函數聲明爲const。由於b也是常量,因此參數必須是常量引用,因爲非常量引用不能綁定到常量對象。因此,這兩個常量的要求。

該參數除了是const以外還有其他選項。它可以通過值來取參數,但這意味着不必要的複製。同樣,如果您選擇聲明非成員operator <,則應該通過const引用(推薦)或值採用這兩個參數。

1

原型爲操作者<是

bool operator<(const Element& b) const { ..... } 

const Element& b意味着元素B的額外副本不會在所述operator<的調用創建以及參數不該方法內修改。第二個const表示調用operator<的對象在調用此調用時不會被修改。

+0

第二個'const'只是承諾比較的對象沒有被修改 – smac89

+0

@ Smac89確實。感謝您指出。 – toro

+0

'operator <'有兩個原型,非成員和成員之一。更常用和推薦的一個是非會員(因爲太長時間無法進入此處),但您已經將會員原型引用爲「原型」。 –

1

據我瞭解,const reference的參數類型提供2個用途:

  1. 從它告訴,參數是不可修改的內部函數體和任何這樣的奇遇會產生編譯器錯誤簽名。
  2. 沒有額外的不必要的key類型的複製。

成員函數由const以便你仍然可以做一個find(或任何其它純讀(除非修改mutable構件)的操作)一個const地圖對象上調用。如果沒有那個const,試圖在const map對象上調用這些成員函數時,會導致編譯錯誤。

當您嘗試創建自定義比較函數時,不需要全局或非成員函數的const

bool operator<(const Key& a, const Key& b) /* no const required here*/ {....} 

const一個功能是隻適用於成員函數,因爲它使this指針或實例的const,其不能成爲全局或非構件比較運算符

的情況下
0

CONST在一種說法是功能看好它的主叫方不會修改傳入的參數時,參數按引用傳遞,以避免額外的副本,但不會修改它往往是需要的,例如:

void function(const Type& var) 
{ 
    // can't modify var here, but can read and call its const methods (see below) 
} 

方法聲明中的Const是一種方法,承諾不修改它所調用的對象的內部狀態。例如

void Class::function(const Type& var) const 
{ 
    // can't modify var here 
    // can't modify "this" here (call other non const methods or change member variables) 
} 

那些承諾可以被打破(這是C++中,我們所談論的畢竟)鑄造常量性了,但是這是意圖反正。

總是要求儘可能少的東西是個好主意。如果方法不改變一個對象 - 聲明它爲const,那麼你可以在該類的一個const實例上調用這個方法(例如,當它作爲一個const引用傳遞給其他地方時)。

在std :: map上定製operator <的情況下,不能在參數中使用非const引用的原因是因爲std :: map會在一個或多個自己的方法中調用你的運算符,被自己聲明爲const。編譯器不允許它將const對象傳遞到不承諾不修改它的函數中。

你不能聲明operator <本身非const的原因(假設它不是一個獨立函數,而是你自定義類的一個方法用作鍵)是一樣的 - std :: map已經答應不要修改密鑰(這會對一個排序造成嚴重破壞),所以它不能調用任何不能保證不變的方法。

定製operator <當用於排序容器內部也有其他要求 - 它必須滿足LessThanComparable概念。