C++ STL map容器基于红黑树实现,提供有序键值对存储,支持O(logN)时间复杂度的查找、插入和删除。其核心操作包括:使用下标[]插入或更新(可能触发默认构造)、insert()插入并返回是否成功(不更新已存在键)、emplace()原地构造提升性能、try_emplace()(C++17)避免重复插入;访问时推荐find()判断存在性并获取迭代器,避免[]隐式插入,或用at()抛异常确保安全;遍历时元素按键升序排列,可使用范围for循环或迭代器;删除需注意erase(key)返回数量,erase(iterator)返回下一有效迭代器,循环中应it = erase(it)避免失效。最佳实践:优先用find()进行安全查找,emplace/try_emplace优化插入,循环删除时利用erase返回值更新迭代器,避免未定义行为。

C++ STL
map
map
map
掌握C++
map
1. 插入键值对: 你可以通过多种方式向
map
[]
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<std::string, int> scores;
// 方式一:使用下标运算符[]
scores["Alice"] = 95; // 插入新键值对
scores["Bob"] = 88; // 插入新键值对
scores["Alice"] = 98; // 更新Alice的分数
// 方式二:使用insert()方法
// insert()返回一个pair<iterator, bool>,bool表示是否成功插入
auto result1 = scores.insert({"Charlie", 70});
if (result1.second) {
std::cout << "Charlie inserted successfully." << std::endl;
}
// 尝试插入已存在的键,insert()会失败,不会更新值
auto result2 = scores.insert({"Bob", 90});
if (!result2.second) {
std::cout << "Bob already exists, value not updated by insert(). Current score: " << scores["Bob"] << std::endl;
}
// 方式三:使用emplace(),原地构造,效率可能更高
scores.emplace("David", 85);
// 方式四:C++17引入的try_emplace,如果键不存在则插入,如果存在则不做任何操作
scores.try_emplace("Eve", 100); // 插入
scores.try_emplace("Bob", 99); // Bob已存在,不会更新值
// 打印所有元素
for (const auto& pair : scores) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}2. 访问键值对: 访问元素同样可以使用下标运算符
[]
[]
at()
// 访问元素
std::cout << "Alice's score: " << scores["Alice"] << std::endl; // 访问已存在的键
// 使用at()访问,如果键不存在会抛出std::out_of_range异常
try {
std::cout << "David's score: " << scores.at("David") << std::endl;
std::cout << "Frank's score: " << scores.at("Frank") << std::endl; // Frank不存在,会抛异常
} catch (const std::out_of_range& e) {
std::cerr << "Error: " << e.what() << std::endl;
}3. 删除键值对: 删除操作可以通过键、迭代器或范围进行。
// 删除元素
scores.erase("Charlie"); // 按键删除
std::cout << "After deleting Charlie:" << std::endl;
for (const auto& pair : scores) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
// 使用迭代器删除
auto it = scores.find("Eve");
if (it != scores.end()) {
scores.erase(it);
std::cout << "After deleting Eve:" << std::endl;
for (const auto& pair : scores) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
}
// 清空map
scores.clear();
std::cout << "Map size after clear: " << scores.size() << std::endl;4. 遍历键值对: 由于
map
// 重新填充map用于遍历示例
scores["Zoe"] = 77;
scores["Amy"] = 90;
scores["Chris"] = 80;
// 范围for循环遍历 (C++11及更高版本)
std::cout << "Iterating with range-based for loop:" << std::endl;
for (const auto& pair : scores) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
// 使用迭代器遍历
std::cout << "Iterating with explicit iterators:" << std::endl;
for (std::map<std::string, int>::iterator it = scores.begin(); it != scores.end(); ++it) {
std::cout << it->first << ": " << it->second << std::endl;
}map
说实话,刚开始用
map
[]
insert
首先,最常见的
map[key] = value;
key
map
value
value
value
立即学习“C++免费学习笔记(深入)”;
相比之下,
map.insert({key, value});map.insert(std::make_pair(key, value));
key
insert
pair<iterator, bool>
bool
false
key
[]
map.emplace(key, value);
map
emplace
insert
emplace
最后,C++17引入的
map.try_emplace(key, value);
key
key
[]
总结一下我的经验和建议:
map[key] = value;
map.try_emplace(key, value);
map.insert({key, value});map.emplace(key, value);
map.insert({key, value});bool
理解这些细微差别,能帮助我们写出更健壮、更高效的代码,避免不必要的性能损耗。
map
查找是
map
O(logN)
最直接的查找方式当然是使用
map[key]
key
map[key]
key
map[key]
更安全的查找方式是使用
map.find(key)
find
key
map.end()
map
map.find(key) == map.end()
it->first
it->second
erase
auto it = myMap.find("someKey");
if (it != myMap.end()) {
// 找到了
std::cout << "Value: " << it->second << std::endl;
} else {
// 没找到
std::cout << "Key not found." << std::endl;
}另一种选择是
map.count(key)
map
key
std::map
count(key)
0
1
if (myMap.count("someKey"))find
[]
at
find
最后是
map.at(key)
key
key
std::out_of_range
key
try-catch
我的最佳实践是:
map.find(key)
map.count(key)
map.at(key)
try-catch
map[key]
map
删除
map
map
map.erase(key)
std::map
map.erase(iterator)
map.erase(first_iterator, last_iterator)
最大的坑,往往出现在我们遍历
map
for
map
it
map.erase(it)
it
erase
++it
如何避免迭代器失效问题? 答案就是利用
map.erase(iterator)
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<std::string, int> ages;
ages["Alice"] = 30;
ages["Bob"] = 25;
ages["Charlie"] = 35;
ages["David"] = 20;
ages["Eve"] = 40;
// 需求:删除所有年龄小于30岁的人
for (auto it = ages.begin(); it != ages.end(); ) { // 注意这里,it在循环体内更新
if (it->second < 30) {
std::cout << "Deleting " << it->first << " (Age: " << it->second << ")" << std::endl;
it = ages.erase(it); // 删除当前元素,并更新it为指向下一个有效元素的迭代器
} else {
++it; // 不需要删除,移动到下一个元素
}
}
std::cout << "\nMap after deletion:" << std::endl;
for (const auto& pair : ages) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}在这个示例中,
it = ages.erase(it);
it
++it
其他需要注意的细节:
map.erase(key)
map
map.clear();
erase
O(logN)
map.erase(first, last)
掌握这些删除技巧,尤其是在循环中处理迭代器失效的策略,能让你在实际项目中更加从容地使用
map
以上就是C++STL map容器键值对操作技巧的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号