【C++ STL】map容器的基本使用

map容器

map 是 C++ STL 中最常用的有序关联式容器 ,核心是存储 key-value(键值对),且 key 唯一、自动排序,底层基于红黑树实现,保证增删查改的时间复杂度稳定在O(logn)。
特性:

  • 存储结构:键值对(key-value),每个 key 对应唯一 value
  • 排序规则:默认按 key 升序排列(可自定义排序规则)
  • 可修改性:key 不可修改(需删除后重新插入),value 可直接修改
  • 底层实现:红黑树(平衡二叉树),避免退化成链表,保证高效操作
  • 空值处理:用 [] 访问不存在的 key 时,会自动插入该 keyvalue 为默认值

基本使用

  • 使用 map 必须包含头文件
c++ 复制代码
#include <map> // 核心头文件
  • 初始化
c++ 复制代码
// 1、空map(默认构造函数
// 键(int)值(string)
map<int, string> m1;
// key(可以是自定义类型)
map<pair<int, int>, vector<int>> m2;

// 2、列表初始化(c++ 11)
map<int, string> m3 = {
	{1, "zs"},
	{2, "ls"}
};

// 3、拷贝构造
map<int, string> m4(m3);

// 4、范围初始化
map<int, string> m5(m3.begin(), m3.end());

// 5、自定义键的排序规则
// 这里的排序规则只针对键,可以传入比较函数或者仿函数
map<int, string, greater<int>> m6;

核心操作API

插入元素

  • \]运算符,m\[key\] = value的方式,比较简单(key 不存在则插入,存在则修改 value);

map<int, string> m = {
{1, "zs"},
{2, "ls"}
};

// []插入元素
m[3] = "ww";

cout << m[3] << endl;

复制代码
* insert({key, value}),key 存在则**插入失败**(不修改),返回 pair \<迭代器,bool\>

```c++
map<int, string> m = {
	{1, "zs"},
	{2, "ls"}
};

// insert插入元素
pair<map<int,string>::iterator, bool> ret = m.insert({ 3, "ww" });

cout << ret.second << endl;		// 1

ret = m.insert({ 3, "zl" });
cout << ret.second << endl;		// 0
  • emplace(key, value)原地构造,避免拷贝,性能优于 insert,key 存在则插入失败
  • insert_or_assign(key, value)C++17 新增,key 存在则修改 value,不存在则插入(兼顾 [] 和 insert 的优点)
c++ 复制代码
map<int, string> m = {
	{1, "zs"},
	{2, "ls"}
};

// insert_or_assign插入元素
m.insert_or_assign(3, "ww");

m.insert_or_assign(3, "ll");
cout << m[3] << endl;		// ll

访问元素

  • \] 运算符,不建议使用(不存在则会插入默认值)

c++ 复制代码
map<int, string> m = {
	{1, "zs"},
	{2, "ls"}
};

cout << m.at(2) << endl;
  • 迭代器访问
c++ 复制代码
map<int, string> m = {
	{1, "zs"},
	{2, "ls"}
};

auto ret = m.find(1);
// 这里必须判断是否找到元素
if (ret != m.end())
{
	cout << ret->first << ":" << ret->second << endl;
}

查找元素

  • find,返回迭代器,如果未找到返回m.end()
c++ 复制代码
map<int, string> m = {
	{1, "zs"},
	{2, "ls"}
};

auto ret = m.find(1);
// 这里必须判断是否找到元素
if (ret != m.end())
{
	cout << ret->first << ":" << ret->second << endl;
}
  • count(),仅判断是否存在

删除元素

  • 按key删除,返回删除元素的个数
c++ 复制代码
map<int, string> m = {
	{1, "zs"},
	{2, "ls"}
};

int ret = m.erase(1);
cout << ret << endl;		// 1
  • 按迭代器删除
c++ 复制代码
map<int, string> m = {
	{1, "zs"},
	{2, "ls"}
};

auto ret = m.find(1);
// 这里必须判断是否找到元素
if (ret != m.end())
{
	// 返回的是迭代器
	auto re = m.erase(ret);
	cout << re->second << endl;
}
  • 删除范围,左开右闭
c++ 复制代码
map<int, string> m = {
	{1, "zs"},
	{2, "ls"}
};

m.erase(m.begin(), m.find(2));
  • clear清空所有元素

遍历元素

  • 普通迭代器,可读写
c++ 复制代码
map<int, string> m = {
	{1, "zs"},
	{2, "ls"}
};

for (map<int, string>::iterator it = m.begin(); it!= m.end(); ++it)
{
	cout << "key = " << it->first << ", value = " << it->second << endl;
}
  • const迭代器,只读
c++ 复制代码
map<int, string> m = {
	{1, "zs"},
	{2, "ls"}
};

for (map<int, string>::const_iterator it = m.cbegin(); it!= m.cend(); ++it)
{
	cout << "key = " << it->first << ", value = " << it->second << endl;
}
  • 范围for循环(c++11)
c++ 复制代码
map<int, string> m = {
	{1, "zs"},
	{2, "ls"}
};

for (auto& p : m)
{
	cout << p.first << ": " << p.second << endl;
}
  • 反向迭代器

进阶用法

  • 自定义排序规则
    • 按key降序
c++ 复制代码
map<int, string, greater<int>> m6;
复制代码
- 自定义排序函数
c++ 复制代码
// 按照字符串长度排序(倒序)
struct strLenCmp {
	bool operator()(const string& a, const string& b) const
	{
		return a.size() > b.size();
	}
};

int main()
{
	map<string, string, strLenCmp> m = {
		{"aaa", "a"},
		{"bbbb", "b"},
		{"ccccc", "c"}
	};

	for (auto& p : m) {
		cout << p.first << endl;
	}

	return EXIT_SUCCESS;
};
复制代码
- 若 `key` 是自定义结构体 / 类,必须重载 `<` 运算符(满足排序规则)
  • 性能优化
    • 避免频繁使用 [] 访问不存在的 key(会自动插入默认值,浪费内存);
    • 插入大量元素时,优先用 emplace() 而非 insert()(原地构造,减少拷贝);
    • 遍历只读场景用 const 迭代器(避免误修改,且性能略优);
    • 若无需有序,优先用 unordered_map(哈希表,平均查找 O(1))。

结束语

  • map 核心是有序唯一键值对 ,底层红黑树保证 O(logn) 操作效率,默认按 key 升序排列;
  • 插入优先用 emplace()(高性能),访问优先用 find()+ 迭代器(避免 [] 自动插入空值),删除用 erase(key)(最直观);
  • 自定义 key 需重载 < 运算符,自定义排序需传入仿函数,只读遍历用 const 迭代器更安全。
相关推荐
曹牧19 小时前
Java:驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立连接
java·开发语言·ssl
郝学胜-神的一滴19 小时前
Linux高性能网络编程基石:epoll核心与文件描述符限制全解
linux·服务器·网络·c++·后端
cch891819 小时前
PHP vs C++:10倍性能差距的编程语言对决
android·java·开发语言
房开民1 天前
c++总结
java·开发语言·c++
好大哥呀1 天前
C++ 多态
java·jvm·c++
毕设源码-赖学姐1 天前
【开题答辩全过程】以 基于Java的医院器材管理系统的设计与实现为例,包含答辩的问题和答案
java·开发语言
float_com1 天前
【java常用API】----- Arrays
java·开发语言
LuckyTHP1 天前
迁移shibboleth java获取shibboleth用户信息
java·开发语言
墨韵流芳1 天前
CCF-CSP第41次认证第三题——进程通信
c++·人工智能·算法·机器学习·csp·ccf
客卿1231 天前
数论===质数统计(暴力法,)
java·开发语言