C++ 映射

C++ 映射

映射 (Map) 以"键/值"对的形式存储元素。

映射中的元素:

  • 通过键(而非索引)访问,每个键都是唯一的
  • 自动按键的升序排序

要使用映射,需要包含 <map> 头文件:

// 包含映射库
#include <map>

创建映射

使用 map 关键字创建映射,在尖括号 <> 中指定键和值的类型,然后指定映射名称,格式为:

map<keytype, valuetype> mapName

实例

// 创建一个名为 people 的映射,键为字符串,值为整数
map<string, int> people

如果要在声明时添加元素,可以将元素放在花括号 {} 内的逗号分隔列表中:

实例

// 创建存储人名和年龄的映射
map<string, int> people = { {"Bill", 19}, {"Steve", 32}, {"Elon", 26} };

访问映射元素

不能像数组和向量那样通过索引号访问映射元素,而是通过方括号 [] 内的键来访问:

实例

// 创建存储人名和年龄的映射
map<string, int> people = { {"Bill", 19}, {"Steve", 32}, {"Elon", 26} };

// 获取键 "Bill" 对应的值
cout << "Bill is: " << people["Bill"] << "\n";

// 获取键 "Steve" 对应的值
cout << "Steve is: " << people["Steve"] << "\n";

亲自试一试

也可以使用 .at() 函数访问元素:

实例

// 创建存储人名和年龄的映射
map<string, int> people = { {"Bill", 19}, {"Steve", 32}, {"Elon", 26} };

// 获取键 "Steve" 对应的值
cout << "Steve is: " << people.at("Steve") << "\n";

// 获取键 "Elon" 对应的值
cout << "Elon is: " << people.at("Elon") << "\n";

亲自试一试

注意:.at() 函数通常比方括号 [] 更受青睐,因为如果元素不存在它会抛出错误信息:

实例

// 创建存储人名和年龄的映射
map<string, int> people = { {"Bill", 19}, {"Steve", 32}, {"Elon", 26} };

// 尝试访问不存在的元素(将抛出异常)
cout << people.at("Jack");

亲自试一试

修改值

可以修改与键关联的值:

实例

map<string, int> people = { {"Bill", 19}, {"Steve", 32}, {"Elon", 26} };

// 将 Bill 的值从 19 改为 50
people["Bill"] = 50;

cout << "Bill is: " << people["Bill"];  // 现在输出 Bill is: 50

亲自试一试

不过使用 .at() 函数更安全:

实例

map<string, int> people = { {"Bill", 19}, {"Steve", 32}, {"Elon", 26} };

// 将 Bill 的值从 19 改为 50
people.at("Bill") = 50;

cout << "Bill is: " << people.at("Bill");  // 现在输出 Bill is: 50

亲自试一试

添加元素

可以使用方括号 [] 向映射添加元素:

实例

map<string, int> people = { {"Bill", 19}, {"Steve", 32}, {"Elon", 26} };

// 添加新元素
people["Jack"] = 23;
people["John"] = 25;
people["Percy"] = 18;
people["Alfred"] = 36;

亲自试一试

也可以使用 .insert() 函数:

实例

map<string, int> people = { {"Bill", 19}, {"Steve", 32}, {"Elon", 26} };

// 添加新元素
people.insert({"Jack", 23});
people.insert({"John", 25});
people.insert({"Percy", 18});
people.insert({"Alfred", 36});

亲自试一试

相同键的元素

映射不能有相同键的元素。

例如,如果我们尝试向映射添加两次 "Jack",它只会保留第一个:

实例

map<string, int> people = { {"Bill", 19}, {"Steve", 32}, {"Elon", 26} };

// 尝试添加两个键相同的元素
people.insert({"Jack", 23});
people.insert({"Jack", 30});

亲自试一试

总结:值可以相同,但键必须唯一。

移除元素

要从映射中移除特定元素,可以使用 .erase() 函数:

实例

map<string, int> people = { {"Bill", 19}, {"Steve", 32}, {"Elon", 26} };

// 通过键移除元素
people.erase("Bill");

亲自试一试

要移除映射中的所有元素,可以使用 .clear() 函数:

实例

map<string, int> people = { {"Bill", 19}, {"Steve", 32}, {"Elon", 26} };

// 移除所有元素
people.clear();

获取映射大小

要获取映射中元素的数量,可以使用 .size() 函数:

实例

map<string, int> people = { {"Bill", 19}, {"Steve", 32}, {"Elon", 26} };
cout << people.size();  // 输出 3

亲自试一试

检查映射是否为空

使用 .empty() 函数检查映射是否为空。

如果映射为空,.empty() 函数返回 1(true),否则返回 0(false):

实例

map<string, int> people;
cout << people.empty(); // 输出 1(映射为空)

亲自试一试

实例

map<string, int> people = { {"Bill", 19}, {"Steve", 32}, {"Elon", 26} };
cout << people.empty();  // 输出 0(不为空)

亲自试一试

注意:也可以通过 .count(key) 函数检查特定元素是否存在。

如果元素存在返回 1(true),否则返回 0(false):

实例

map<string, int> people = { {"Bill", 19}, {"Steve", 32}, {"Elon", 26} };
cout << people.count("Bill");  // 输出 1(Bill 存在)

亲自试一试

遍历映射

可以使用 for-each 循环遍历映射。但需要注意几点:

  • 应在循环中使用 auto 关键字(C++11 引入),让编译器自动确定每个键值对的正确数据类型
  • 由于映射元素包含键和值,在循环中需要使用 .first 访问键,.second 访问值
  • 映射中的元素按键的升序自动排序

实例

map<string, int> people = { {"Bill", 19}, {"Steve", 32}, {"Elon", 26} };

for (auto person : people) {
  cout << person.first << " is: " << person.second << "\n";
}

亲自试一试

输出结果将是:

Bill is: 19
Elon is: 26
Steve is: 32

如果要反转排序顺序,可以在尖括号中使用 greater<type> 函数对象:

实例

map<string, int, greater<string>> people = { {"Bill", 19}, {"Steve", 32}, {"Elon", 26} };

for (auto person : people) {
  cout << person.first << " is: " << person.second << "\n";
}

亲自试一试

输出结果将是:

Steve is: 32
Elon is: 26
Bill is: 19

提示:也可以使用迭代器遍历映射,这将在下一章中详细介绍。