• 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.

    顺序 选择 循环 总结

  • 相关阅读:
    HTML DOM 事件
    js实现键盘数字输入
    js实现键盘数字输入
    onbeforeunload事件兼容性操作
    onbeforeunload事件兼容性操作
    window.event对象详尽解析
    git简单使用教程
    PHP中奖概率写法
    PHP替代session的方法
    nginx实现负载均衡
  • 原文地址:https://www.cnblogs.com/Braveliu/p/14128342.html
Copyright © 2020-2023  润新知