C++ map容器: 插入操作

1. map插入操作基础

map是C++ STL中的关联容器,存储键值对(key-value pairs)。插入元素时有四种主要方式,各有特点:

1.1 头文件与声明

cpp 复制代码
#include <map>
using namespace std;

map<int, string> mapStu;  // 键为int,值为string

2. 四种插入方式详解

2.1 方式一:构造pair后插入

cpp 复制代码
pair<map<int, string>::iterator, bool> ret = 
    mapStu.insert(pair<int, string>(1, "张三"));

特点:

  • 显式构造pair对象
  • insert返回一个pair<iterator, bool>
    • first:指向插入元素的迭代器
    • second:是否插入成功(bool)

示例判断:

cpp 复制代码
if (ret.second == true) {
    cout << "插入成功!value:" << (*(ret.first)).second << endl;
} else {
    cout << "插入失败!" << endl;  // 键已存在时会失败
}

注意 :对于map,如果键已存在,插入会失败,不会覆盖原有值。

2.2 方式二:使用make_pair

cpp 复制代码
mapStu.insert(make_pair(2, "李四"));

优点:

  • 语法更简洁,无需显式指定模板参数
  • 自动推导pair类型
  • 同样返回pair<iterator, bool>

2.3 方式三:使用value_type

cpp 复制代码
mapStu.insert(map<int, string>::value_type(3, "王五"));

特点:

  • value_type是map内部定义的typedef,等同于pair<const Key, T>
  • 类型安全,确保键的类型正确
  • 同样返回pair<iterator, bool>

2.4 方式四:使用\[\]操作符

cpp 复制代码
mapStu[4] = "赵六";      // 插入
mapStu[4] = "小赵六";    // 修改

关键特性:

  1. 查找+插入/修改:先查找键是否存在,不存在则插入,存在则修改

  2. 可能意外插入 :访问不存在的键时会自动插入

    cpp 复制代码
    string strName = mapStu[8];  // 键8不存在时会自动插入
  3. 返回值:返回值的引用,可直接修改

特殊用法:

cpp 复制代码
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内容

cpp 复制代码
for (map<int, string>::iterator it = mapStu.begin(); 
     it != mapStu.end(); it++) {
    cout << it->first << ", " << it->second << endl;
}

或使用C++11范围for循环:

cpp 复制代码
for (const auto& pair : mapStu) {
    cout << pair.first << ", " << pair.second << endl;
}

5. 关键注意事项

  1. 键的唯一性 :map中每个键只能出现一次,重复插入会失败
  2. 自动排序:元素按键的升序自动排列
  3. \[\]操作符的风险 :
    • 可能意外插入新元素
    • 访问不存在的键时会用默认值创建新元素
  4. 性能考虑 :
    • 插入操作平均时间复杂度O(log n)
    • 对于已知不存在的键,使用insert比[]更高效

6. 实际应用建议

  1. 需要知道是否插入成功 :使用insert+检查返回值
  2. 需要覆盖现有值 :使用[]操作符
  3. 避免意外插入 :先用find检查键是否存在
  4. 代码简洁性 :优先考虑make_pair或emplace(C++11)

7. 完整代码回顾

cpp 复制代码
#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方法:

cpp 复制代码
mapStu.emplace(5, "钱七");  // 直接在容器内构造元素,避免临时对象

8.2 异常安全性

insert和emplace提供强异常保证:如果插入失败,容器保持不变。

8.3 性能优化

对于大批量插入:

  1. 如果键已知有序,可以使用提示位置插入:

    cpp 复制代码
    mapStu.insert(hint_iterator, make_pair(10, "孙八"));
  2. 或者先构建vector再批量插入

相关推荐
程序猿追4 小时前
kotlin-retry 接入鸿蒙后,怎样确认它真的会停止重试
开发语言·kotlin·harmonyos
我是人✓4 小时前
Java文件上传三方式对比:从传统到SpringBoot
java·开发语言
智能直播4 小时前
网络RTMP拉流不卡顿、声音不同步,一文讲透缓冲区、时间戳
开发语言·ffmpeg·php·音视频·视频编解码
墨云安全5 小时前
内网资产无法暴露到公网,怎么做安全检测?2026 年内网渗透测试的落地路径
开发语言·安全·网络安全·渗透测试·php
摇滚侠5 小时前
《计算机是如何工作的:人人都能懂的计算机软硬件工作原理》第 9 章 机器码与汇编语言 阅读笔记 9
java·开发语言·笔记
Cc.Y5 小时前
Java零基础入门:深入Java核心:文件IO与序列化全解
java·开发语言·python
xier_ran5 小时前
【infra之路】AI 编译器学习笔记(六):重拾 C++——lambda 与 MLIR 中的回调
c++·笔记·学习
jimy17 小时前
c++的 Type Traits (一)
开发语言·c++
别动我齐刘海7 小时前
Linux 系统调试学习2
linux·运维·c++·人工智能·学习·机器学习·机器人
Web极客码7 小时前
Python Ollama 本地 Agent 入门与订单查询实践
开发语言·jvm·python