用 operator[] 还是 insert() 取决于是否想覆盖已有键值及是否关心插入结果:operator[] 会默认构造 value 并可能覆盖,insert() 仅在 key 不存在时插入且返回成功标志。
map 插入元素时,用
还是
?
取决于你是否想覆盖已有键值、是否关心插入结果。用
会默认构造 value(哪怕 key 已存在),还可能意外覆盖;
则只在 key 不存在时才插入,返回
告诉你成败。
如果只是“确保有这个键,值无所谓”,
最简,但注意:若
类型无默认构造(比如
),
会编译失败
如果要避免覆盖、或需判断是否真插入了新项,必须用
:
(C++17 结构化绑定)
更高效——它直接在容器内构造节点,避免临时对象拷贝,适合 value 构造开销大时:
遍历 map 时修改元素值,哪些操作安全?
可以安全修改 value,但不能修改 key——因为 key 是排序依据,改了就破坏红黑树结构,行为未定义。
修改 value 完全 OK:
想改 key?不行。得先
再
或
新的键值对
边遍历边
当前迭代器?不安全。要用
返回的下一个有效迭代器:
map 查找失败时,
和
的行为差异
返回
迭代器,安全;
找不到直接抛
异常——它不检查,只信任调用者。
日常查找推荐
:
适合你 100% 确定 key 存在,且希望异常暴露逻辑错误(比如配置项缺失):
别用
查找——它会在 key 不存在时插入默认构造的 value,副作用巨大
性能关键点:map 的 key 类型必须支持严格弱序,且比较廉价
底层是红黑树,所有操作依赖
或自定义比较器。如果 key 比较慢(比如长字符串反复比对),或比较逻辑出错(比如不满足严格弱序),性能会断崖式下跌,甚至导致无限循环。
C知道
CSDN推出的一款AI技术问答工具
下载
立即学习
“
C++免费学习笔记(深入)
”;
自定义结构体作 key 时,必须提供合法的
:
(注意:不能用
或随机逻辑)
字符串 key 优先用
而非
——后者比较的是指针地址,不是内容
如果 key 比较成本高,且查找远多于插入,考虑换
(哈希表),但要注意 hash 和 equality 函数必须一致
最常被忽略的是比较函数的“严格弱序”要求:它必须满足非自反性(
永假)、非对称性(
为真则
必假)、传递性(
⇒
)。写错就会让 map 行为不可预测。
operator[]insert()operator[]insert()std::pairmyMap[key] = valuevaluestd::unique_ptroperator[]insert()auto [it, inserted] = myMap.insert({key, value});emplace()myMap.emplace(key, std::move(value));for (auto& p : myMap) { p.second += 10; }erase()insert()emplace()erase()erase()for (auto it = myMap.begin(); it != myMap.end(); ) { if (shouldRemove(it->first)) it = myMap.erase(it); else ++it; }find()at()find()end()at()std::out_of_rangefind()auto it = myMap.find(key); if (it != myMap.end()) use(it->second);at()try { auto& v = myMap.at("timeout"); } catch (const std::out_of_range&) { /* handle missing config */ }operator[]std::mapoperator<operator<bool operator<(const MyKey& a, const MyKey& b) { return a.id < b.id; }<=std::stringconst char*std::unordered_mapa < aa < bb < aa < b && b < ca < c