簡體   English   中英

使用集作為鍵進行映射的機制

[英]Mechanism of using sets as keys to map

我有這段代碼,我不明白為什么會這樣:

map<set<int>,int> states;
set<int> s1 = {5,1,3}, s2 = {1,5,3};    
states[s1] = 42;
printf("%d", states[s2]); // 42

輸出為42,因此使用狀態鍵的值以某種方式進行比較。 這怎么可能? 我希望這不會像類似的示例那樣起作用:

map<const char*,int> states;
char s1[]="foo", s2[]="foo";
states[s1] = 42;
printf("%d",states[s2]); // not 42

這里char指針的地址用作鍵,而不是它所指向的內存的值,對嗎? 請解釋這兩個示例之間的區別。

編輯:我剛剛發現了一些關於比較對象的東西,這解釋了很多。 但是如何為集合創建比較對象? 我看不到它怎么可能是默認的較少對象。

此行為的一些原因:

  • 在輸入值時,集合將保持排序,因此,如果您將其打印出來,則s1和s2實際上看起來相同。
  • 集具有重載運算符,因此s1 == s2會比較內容
  • 第二個使用* char的示例顯式將指針(地址)作為鍵
  • 聲明靜態字符串將為兩個“ foo”實例提供不同的地址
    • 如果改用s2 = s1,則應該得到相同的行為

您對比較對象有所了解。
C ++ map的模板參數之一定義了充當比較謂詞的對象,默認情況下為std::less<Key> ,在本例中為std::less<set<int>>

來自cplusplus.com

映射對象使用此表達式確定元素在容器中遵循的順序以及兩個元素鍵是否等效(通過反身比較它們:如果!comp(a,b)&&!comp(b,a)等效) 。 地圖容器中沒有兩個元素可以具有等效鍵。

std::less

二進制函數對象類,其調用返回其第一個參數是否小於第二個參數(由operator <返回)。 std::set::key_comp :默認情況下,這是一個較少對象,其返回值與operator<相同。

現在, 小於運算符做什么?

小於比較( operator< )的行為就像使用lexicographical_compare算法一樣,該算法使用倒數方式使用operator<依次比較元素(即檢查a<bb<a )並在第一次出現時停止。

或從MSDN

集合對象之間的比較基於它們的元素的成對比較。 兩個對象之間的小於關系是基於對第一對不相等元素的比較。

因此,由於兩個集合都是等效的,因為set s是按鍵排序的,所以將其中一個用作鍵是指映射中的同一條目。
但是第二個示例使用指針作為鍵,因此兩個等效值在映射范圍內並不相等,因為在任何情況下都沒有以特殊方式定義operator< ,這只是地址之間的比較。 如果您使用std::string作為鍵,則它們將匹配,(因為它們確實具有自己的operator< )。

查看cppreference.com上的文檔:

template<
    class Key,
    class T,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<std::pair<const Key, T> >
> class map;

因此,如果您不提供自己的自定義比較功能,它將通過<運算符對元素進行排序,並且:

operator==,!=,<,<=,>,>=(std::set)...
Compares the contents of lhs and rhs
lexicographically. The comparison is
performed by a function equivalent to 
std::lexicographical_compare.

因此,當您在兩個集合上調用< ,它將按字典順序比較它們的排序元素。 您的兩組在排序時完全相同。

當您這樣做時:

cout << (s1 == s2);

您得到的輸出為1 我不知道C ++中的設置如何工作。 我什至都不知道它們是什么。 我確實知道==比較運算符不會返回集合值是否不相同的順序。 可能會返回這些集合是否包含相同的值,而與順序無關。

編輯:是的,集合已排序。 因此,當您創建它們時,它們會被排序,這意味着它們成為同一件事。 使用std::vectorstd::array

編輯#2:他們確實變得平等。 讓我作個比喻。

int v1 = 4 + 1;
int v2 = 1 + 4;

現在顯然,v1和v2將是相同的值。 集合沒有什么不同; 一旦創建,將對內容進行排序,並在使用==運算符進行比較時(這是std::map如何部分標識映射的元素),它將返回“是,它們相等”。 這就是您的代碼如何工作的原因。

暫無
暫無

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

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