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.
顺序 选择 循环 总结
分类:
[01]【C/C++】
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
2019-12-13 C++ Primer Plus 第六版 代码笔记
2018-12-13 windows10 安装 mysql8.0.12 详解