先说结论
在 C++ 的 std::map 中,无论是 insert 还是 emplace,当 key 已经存在时都不会覆盖原有的值。两者都遵循“只插入、不更新”的语义:如果容器中已经存在等价 key,插入操作直接失败(或什么都不做),原有 value 保持不变。
真正会覆盖已有值的是 operator[] 和 insert_or_assign。这是很多初学者容易混淆的地方。
insert 的行为
insert 的返回值是一个 pair<iterator, bool>,其中 bool 表示是否插入成功。key 已存在时返回 false,迭代器指向已存在的那个元素,值不会被修改。
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<std::string, int> m;
m.insert({"apple", 1});
auto ret = m.insert({"apple", 100});
std::cout << "inserted: " << ret.second << "\\n"; // 0
std::cout << "value: " << m["apple"] << "\\n"; // 1,未被覆盖
return 0;
}
可以看到,第二次插入的 100 被直接丢弃,m["apple"] 仍然是 1。
emplace 的行为
emplace 同样是“只在 key 不存在时构造并插入”。它的返回值与 insert 一致,也是 pair<iterator, bool>。key 已存在时返回 false,并且不会用新参数去覆盖旧值。
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<std::string, int> m;
m.emplace("apple", 1);
auto ret = m.emplace("apple", 100);
std::cout << "inserted: " << ret.second << "\\n"; // 0
std::cout << "value: " << m["apple"] << "\\n"; // 1,未被覆盖
return 0;
}
insert 与 emplace 的区别
两者在“是否覆盖”这一点上没有区别,真正的差异在于构造时机和参数传递方式:
- insert 通常需要先构造出一个 value_type(即 pair<const Key, T>),再把它拷贝或移动到容器中。
- emplace 接受构造参数,直接在容器内部原地构造元素,理论上可以少一次临时对象的构造和拷贝。
但要注意:emplace 并不保证一定比 insert 快。如果 key 已存在,emplace 仍然可能先构造出临时对象再发现重复而丢弃,此时反而可能比 insert 多做一次构造。因此不能盲目认为 emplace 总是更优。
那什么操作会覆盖?
如果确实希望在 key 存在时更新值,应该使用下面两种方式:
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<std::string, int> m;
m["apple"] = 1;
// 方式一:operator[],key 不存在会默认构造,存在则覆盖
m["apple"] = 100;
std::cout << m["apple"] << "\\n"; // 100
// 方式二:insert_or_assign(C++17),语义更明确
m.insert_or_assign("apple", 200);
std::cout << m["apple"] << "\\n"; // 200
return 0;
}
两者的区别在于:operator[] 在 key 不存在时会先默认构造一个 value,要求 T 可默认构造;而 insert_or_assign 不存在时直接插入,不要求默认构造,语义也更清晰。
对比总结
| insert | 不插入,不覆盖 | pair<iterator, bool> |
| emplace | 不插入,不覆盖 | pair<iterator, bool> |
| operator[] | 覆盖(不存在则默认构造) | 值的引用 |
| insert_or_assign | 覆盖(不存在则插入) | pair<iterator, bool> |
一句话记忆:insert 和 emplace 都是“插入”,不是“赋值”;要覆盖请用 operator[] 或 insert_or_assign。
网硕互联帮助中心



评论前必须登录!
注册