C++ map容器: 插入操作
1. map插入操作基础
map
是C++ STL中的关联容器,存储键值对(key-value pairs)。插入元素时有四种主要方式,各有特点:
1.1 头文件与声明
#include <map>
using namespace std;map<int, string> mapStu; // 键为int,值为string
2. 四种插入方式详解
2.1 方式一:构造pair后插入
pair<map<int, string>::iterator, bool> ret = mapStu.insert(pair<int, string>(1, "张三"));
特点:
- 显式构造
pair
对象 insert
返回一个pair<iterator, bool>
first
:指向插入元素的迭代器second
:是否插入成功(bool)
示例判断:
if (ret.second == true) {cout << "插入成功!value:" << (*(ret.first)).second << endl;
} else {cout << "插入失败!" << endl; // 键已存在时会失败
}
注意:对于map
,如果键已存在,插入会失败,不会覆盖原有值。
2.2 方式二:使用make_pair
mapStu.insert(make_pair(2, "李四"));
优点:
- 语法更简洁,无需显式指定模板参数
- 自动推导pair类型
- 同样返回
pair<iterator, bool>
2.3 方式三:使用value_type
mapStu.insert(map<int, string>::value_type(3, "王五"));
特点:
value_type
是map内部定义的typedef,等同于pair<const Key, T>
- 类型安全,确保键的类型正确
- 同样返回
pair<iterator, bool>
2.4 方式四:使用[]操作符
mapStu[4] = "赵六"; // 插入
mapStu[4] = "小赵六"; // 修改
关键特性:
- 查找+插入/修改:先查找键是否存在,不存在则插入,存在则修改
- 可能意外插入:访问不存在的键时会自动插入
string strName = mapStu[8]; // 键8不存在时会自动插入
- 返回值:返回值的引用,可直接修改
特殊用法:
mapStu[6] = mapStu[5]; // 复制键5的值到键6
mapStu[7] = mapStu[4]; // 复制键4的值到键7
3. 四种方式对比
特性 | 方式一(pair) | 方式二(make_pair) | 方式三(value_type) | 方式四([]) |
---|---|---|---|---|
语法复杂度 | 高 | 中 | 高 | 低 |
返回值 | pair<iter,bool> | pair<iter,bool> | pair<iter,bool> | 值引用 |
键存在时的行为 | 不覆盖 | 不覆盖 | 不覆盖 | 覆盖 |
可能意外插入 | 否 | 否 | 否 | 是 |
类型安全性 | 高 | 中 | 最高 | 低 |
性能 | 中等 | 中等 | 中等 | 稍快 |
4. 遍历map内容
for (map<int, string>::iterator it = mapStu.begin(); it != mapStu.end(); it++) {cout << it->first << ", " << it->second << endl;
}
或使用C++11范围for循环:
for (const auto& pair : mapStu) {cout << pair.first << ", " << pair.second << endl;
}
5. 关键注意事项
- 键的唯一性:
map
中每个键只能出现一次,重复插入会失败 - 自动排序:元素按键的升序自动排列
- []操作符的风险:
- 可能意外插入新元素
- 访问不存在的键时会用默认值创建新元素
- 性能考虑:
- 插入操作平均时间复杂度O(log n)
- 对于已知不存在的键,使用
insert
比[]
更高效
6. 实际应用建议
- 需要知道是否插入成功:使用
insert
+检查返回值 - 需要覆盖现有值:使用
[]
操作符 - 避免意外插入:先用
find
检查键是否存在 - 代码简洁性:优先考虑
make_pair
或emplace
(C++11)
7. 完整代码回顾
#include <map>
#include <iostream>using namespace std;int main() {map<int, string> mapStu;// 方式一auto ret = mapStu.insert(pair<int, string>(1, "张三"));if (ret.second) {cout << "插入成功!value:" << ret.first->second << endl;} else {cout << "插入失败!" << endl;}// 重复插入测试ret = mapStu.insert(pair<int, string>(1, "小张三"));if (!ret.second) {cout << "插入小张三失败!" << endl;}// 方式二mapStu.insert(make_pair(2, "李四"));// 方式三mapStu.insert(map<int, string>::value_type(3, "王五"));// 方式四mapStu[4] = "赵六";mapStu[4] = "小赵六"; // 覆盖// 特殊用法mapStu[6] = mapStu[5]; // 复制mapStu[7] = mapStu[4]; // 复制// 遍历输出for (const auto& pair : mapStu) {cout << pair.first << ", " << pair.second << endl;}system("pause");return 0;
}
8. 扩展知识
8.1 C++11的emplace
C++11引入了更高效的emplace
方法:
mapStu.emplace(5, "钱七"); // 直接在容器内构造元素,避免临时对象
8.2 异常安全性
insert
和emplace
提供强异常保证:如果插入失败,容器保持不变。
8.3 性能优化
对于大批量插入:
- 如果键已知有序,可以使用提示位置插入:
mapStu.insert(hint_iterator, make_pair(10, "孙八"));
- 或者先构建vector再批量插入