云计算百科
云计算领域专业知识百科平台

C++ 中 map 的 insert 与 emplace:key 已存在时会覆盖吗?

先说结论

在 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 不存在时直接插入,不要求默认构造,语义也更清晰。

对比总结

操作key 已存在时的行为返回值
insert 不插入,不覆盖 pair<iterator, bool>
emplace 不插入,不覆盖 pair<iterator, bool>
operator[] 覆盖(不存在则默认构造) 值的引用
insert_or_assign 覆盖(不存在则插入) pair<iterator, bool>

一句话记忆:insert 和 emplace 都是“插入”,不是“赋值”;要覆盖请用 operator[] 或 insert_or_assign。

赞(0)
未经允许不得转载:网硕互联帮助中心 » C++ 中 map 的 insert 与 emplace:key 已存在时会覆盖吗?
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!