std::map 自定義類型作為key


昨天給同事寫了一個把自定義類型作為map中key值的示例,結果過了半個小時,同事反饋:不滿足需求。

嗯哼?作為一個程序員,不滿足需求那可就是BUG呀~ 不行,得盡快給處理一下。

【1】異常示例(不滿足需求樣例)

源代碼如下:

 1 #include <map>
 2 #include <string>
 3 #include <iostream>
 4 using namespace std;  5 
 6 struct SNCloneInfo  7 {  8     int cloneId;  9     std::string type; 10 }; 11 
12 struct SNCloneCompare 13 { 14     bool operator()(const SNCloneInfo& p1, const SNCloneInfo& p2) const
15  { 16         return (p1.cloneId < p2.cloneId) || (p1.cloneId == p2.cloneId && p1.type.size() < p2.type.size()); 17  } 18 }; 19 
20 struct SNCloneInfoRepo 21 { 22     void create(SNCloneInfo src, SNCloneInfo dst) 23  { 24         m_mapRelations[src] = dst; 25  } 26     SNCloneInfo find(int id, std::string type) 27  { 28         return m_mapRelations[SNCloneInfo{ id, type }]; 29  } 30 
31     std::map<SNCloneInfo, SNCloneInfo, SNCloneCompare> m_mapRelations;
32 }; 33 
34 int main() 35 { 36  SNCloneInfoRepo repo; 37     repo.create(SNCloneInfo{ 0, "abc" }, SNCloneInfo{ 0, "abc" }); 38     repo.create(SNCloneInfo{ 0, "abcd" }, SNCloneInfo{ 1, "abc" }); 39     repo.create(SNCloneInfo{ 0, "bcd" }, SNCloneInfo{ 1, "abc" }); 40     repo.create(SNCloneInfo{ 1, "bcd" }, SNCloneInfo{ 0, "bcd" }); 41     repo.create(SNCloneInfo{ 2, "cde" }, SNCloneInfo{ 0, "cde" }); 42 
43     cout << "repo size : " << repo.m_mapRelations.size() << endl; 44     for (auto& item : repo.m_mapRelations) 45  { 46         cout << "K[ " << item.first.cloneId << "," << item.first.type << " ] -->"
47             << "V[ " << item.second.cloneId << "," << item.second.type << " ]" << endl; 48  } 49     auto temp = repo.find(0, "abc"); 50     cout << "temp info cloneid : " << temp.cloneId << " || type : " << temp.type << endl; 51 
52     return 0; 53 }

運行結果如下圖:

【2】正常示例(滿足需求樣例)

源代碼如下:

 1 #include <map>
 2 #include <string>
 3 #include <iostream>
 4 using namespace std;
 5 
 6 struct SNCloneInfo
 7 {
 8     int cloneId;
 9     std::string type;
10 };
11 
12 struct SNCloneCompare 
13 {
14     bool operator()(const SNCloneInfo& p1, const SNCloneInfo& p2) const
15     {
16         return (p1.cloneId < p2.cloneId) || (p1.cloneId == p2.cloneId && p1.type < p2.type);
17     }
18 };
19 
20 struct SNCloneInfoRepo
21 {
22     void create(SNCloneInfo src, SNCloneInfo dst)
23     {
24         m_mapRelations[src] = dst;
25     }
26     SNCloneInfo find(int id, std::string type)
27     {
28         return m_mapRelations[SNCloneInfo{ id, type }];
29     }
30 
31     std::map<SNCloneInfo, SNCloneInfo, SNCloneCompare> m_mapRelations;
32 };
33 
34 int main()
35 {
36     SNCloneInfoRepo repo;
37     repo.create(SNCloneInfo{ 0, "abc" }, SNCloneInfo{ 0, "abc" });
38     repo.create(SNCloneInfo{ 0, "abcd" }, SNCloneInfo{ 1, "abc" });
39     repo.create(SNCloneInfo{ 0, "bcd" }, SNCloneInfo{ 1, "abc" });
40     repo.create(SNCloneInfo{ 1, "bcd" }, SNCloneInfo{ 0, "bcd" });
41     repo.create(SNCloneInfo{ 2, "cde" }, SNCloneInfo{ 0, "cde" });
42 
43     cout << "repo size : " << repo.m_mapRelations.size() << endl;
44     for (auto& item : repo.m_mapRelations)
45     {
46         cout << "K[ " << item.first.cloneId << "," << item.first.type << " ] -->"
47             << "V[ " << item.second.cloneId << "," << item.second.type << " ]" << endl;
48     }
49     auto temp = repo.find(0, "abc");
50     cout << "temp info cloneid :  " << temp.cloneId << " || type : " << temp.type << endl;
51 
52     return 0;
53 }

運行結果如下圖:

【3】總結

代碼很簡單,不做贅述。只講差異點:

第一個示例,明明存進去了5個鍵值對,結果打印個數只有4個!!

經全部打印值分析,很明確錯誤原因:比較函數中當cloneId相同時,對字符串類型type值作了長度比較。

第一次插入的鍵為“0, abc”,第三次插入的鍵為“0, bcd”,cloneId相同,且兩個鍵type值長度相同,map將其視作相同的鍵,然后把鍵“0,abc”的值替換為“1,abc”完畢。

經更正,詳見第二個示例效果。

以此備錄,警醒自己。

 

good good study, day day up.

順序 選擇 循環 總結


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM