跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

C++ map 与 multimap 核心用法及底层原理

C++ map 基于红黑树实现 Key-Value 映射,Key 有序且唯一。multimap 允许 Key 重复但不支持 [] 操作符。插入数据常用 insert 配合 pair 或 make_pair,C++11 支持初始化列表。operator[] 在 Key 不存在时会自动插入默认值并返回引用,常用于计数统计。遍历迭代器按 Key 升序排列,修改 Value 安全但修改 Key 会破坏树结构。

JavaCoder发布于 2026/3/24更新于 2026/5/2114 浏览
C++ map 与 multimap 核心用法及底层原理

C++ map 与 multimap 核心用法及底层原理

map 类简介

map 是 C++ STL 中基于红黑树实现的关联容器,存储 Key-Value 键值对。Key 必须支持小于比较(默认 less<Key>),且 Key 唯一有序。底层内存由空间配置器管理,增删查改时间复杂度为 O(logN)。迭代器遍历时按 Key 升序排列。

template<class Key, class T, class Compare = less<Key>, class Alloc = allocator<pair<const Key, T>>>
class map;

通常开发中只需关注前两个模板参数,后两个使用默认值即可。

pair 类型基础

map 内部存储的是 pair<const Key, T> 结构。pair 是一个类模板,将两个不同类型的数据耦合在一起,成员包括 first (Key) 和 second (Value)。

template<class T1, class T2>
struct pair {
    typedef T1 first_type;
    typedef T2 second_type;
    T1 first;
    T2 second;
    // ... 构造函数省略
};

在 map 中,first 对应 Key,second 对应 Value。理解 pair 是掌握 map 操作的关键。

map 的构造与遍历

map 支持多种构造方式,包括默认构造、范围构造、拷贝构造以及初始化列表构造。由于底层是二叉搜索树,正向迭代器遍历默认按 Key 升序。

注意: map 支持修改 Value 数据,但不支持直接修改 Key 数据。修改 Key 会破坏红黑树的结构平衡。

// 初始化列表构造 (C++11)
map<string, int> scores = {{"Alice", 90}, {"Bob", 85}};

// 遍历
for (auto it = scores.begin(); it != scores.end(); ++it) {
    cout << it->first <<  << it->second << endl;
}
": "

map 的插入机制

插入数据有多种方式,核心都是向容器中添加 pair<const Key, T> 对象。

常见插入方法

  1. 显式创建 pair 对象:语义清晰,适合复杂类型。
  2. make_pair 函数:自动推导类型,减少代码量。
  3. 初始化列表:C++11 起支持,最简洁。
map<string, string> dict;

// 法一:有名 pair
pair<string, string> kv("left", "左边");
dict.insert(kv);

// 法二:匿名 pair
dict.insert(pair<string, string>("right", "右边"));

// 法三:make_pair (自动推导)
dict.insert(make_pair("insert", "插入"));

// 法四:初始化列表 (推荐)
dict.insert({"string", "字符串"});

返回值与重复 Key

insert 返回一个 pair<iterator, bool>。如果 Key 已存在,插入失败,返回的 bool 为 false,迭代器指向已有元素;如果插入成功,bool 为 true。

这意味着即使传入相同的 Key,只要 Value 不同,也不会覆盖旧值,插入操作依然会失败。这与 operator[] 的行为有本质区别。

operator[] 的魔法

operator[] 是 map 中最常用的操作符,它集成了查找、插入和修改功能。

int main() {
    map<string, int> countMap;
    string arr[] = {"苹果", "西瓜", "苹果", "西瓜", "苹果"};

    for (const auto& str : arr) {
        countMap[str]++;  // 一行搞定统计逻辑
    }
    return 0;
}

底层原理

为什么 countMap[str]++ 能同时处理'不存在'和'存在'的情况?

  1. 查找或插入:operator[] 内部先调用 insert(make_pair(k, mapped_type()))。如果 Key 不存在,它会插入一个默认构造的 Value(例如 int 默认为 0)。
  2. 返回引用:无论插入是否成功,它都返回该 Key 对应 Value 的引用。
  3. 自增:拿到引用后执行 ++,如果是新插入的则为 1,如果是已有的则累加。

这种设计让计数统计变得异常简单,但也意味着每次访问都会尝试插入默认值,性能上略低于 find + insert 的组合,但在可读性上优势明显。

注意事项

  • Key 不可变:通过 operator[] 获取的 Value 引用可以修改,但 Key 不能改。
  • multimap 不支持:由于 multimap 允许 Key 重复,operator[] 无法确定返回哪个 Key 对应的 Value,因此 multimap 不提供此操作符。

multimap 与 map 的差异

multimap 的使用接口与 map 高度相似,主要区别在于 Key 的冗余性。

特性mapmultimap
Key 唯一性唯一可重复
operator[]支持不支持
equal_range返回单元素范围返回多元素范围

当需要存储多个相同 Key 的值时(如学生成绩表,同一科目多次考试),应使用 multimap。

equal_range 接口

equal_range 用于获取相等元素的范围,返回一对迭代器 [first, last)。在 multimap 中,这非常有用,因为它能一次性取出所有相同 Key 的记录。

std::multimap<char, int> mymm;
mymm.insert(std::make_pair('a', 10));
mymm.insert(std::make_pair('b', 20));
mymm.insert(std::make_pair('b', 30));

auto range = mymm.equal_range('b');
for (auto it = range.first; it != range.second; ++it) {
    cout << it->second << endl;
}

总结

  • map 基于红黑树,Key 有序且唯一,O(logN) 效率。
  • 插入常用 insert 配合 pair 或 make_pair,C++11 支持 {} 语法。
  • operator[] 会自动插入默认值并返回引用,适合计数场景,但 multimap 不支持。
  • multimap 允许 Key 重复,需配合 equal_range 使用。

掌握这些细节,能让你在处理关联数据时更加得心应手。

目录

  1. C++ map 与 multimap 核心用法及底层原理
  2. map 类简介
  3. pair 类型基础
  4. map 的构造与遍历
  5. map 的插入机制
  6. 常见插入方法
  7. 返回值与重复 Key
  8. operator[] 的魔法
  9. 底层原理
  10. 注意事项
  11. multimap 与 map 的差异
  12. equal_range 接口
  13. 总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • C++ 核心基础概念梳理
  • 从销售助理转行软件测试:零经验求职与学习路径分享
  • AI 辅助编程:工具使用与实战技巧
  • 链表基础算法总结与经典题目解析
  • Kali Linux 系统安装与基础配置指南
  • GitHub Copilot 使用体验与功能场景分析
  • C++ 二叉树层序遍历:在每个树行中找最大值
  • 数据结构:堆、哈希表与字符串哈希详解
  • Discord 机器人创建与配置完整流程
  • Java Web 开发环境搭建:IDEA 与 Tomcat 安装部署指南
  • Flutter 三方库 discord_interactions 在 OpenHarmony 上的适配指南
  • 老旧笔记本部署飞牛 NAS 及常见问题解决方案
  • Web 虚拟卡销售平台完整实现方案
  • C++ 核心基础概念梳理:命名空间、引用与重载
  • Python 鼻炎在线预约挂号评价系统微信小程序设计与开发
  • C++ 继承机制详解:从基础到虚拟继承
  • WebGIS 实战:WKT 转 GeoJSON 技巧与 Leaflet 集成
  • C++ 基础入门:数据类型、IO 流与常用容器
  • Midjourney AI 绘图工具实战测评
  • 无人机经典教材 MAVSim 仿真资源与代码实践

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online