昨天給同事寫了一個把自定義類型作為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.
順序 選擇 循環 總結