try_emplace与find+insert效率对比及嵌套map用法解析
关于
std::map::try_emplace的效率与嵌套map使用问题 问题背景
初始定义的结构体与map:
typedef struct st_A{ int a = 0; string s; st_A(const int a, const string&s) :a(a),s(s) {} }st_A; map<string, st_A> m1;
原插入逻辑(find+insert):
if (auto it = m1.find("c1"); it == m1.end()){ //未找到 m1.insert({ "c1", {10, "c"} }); }else{ // 通过it进行更新 }
改用try_emplace的实现:
auto [it, inserted] = m1.try_emplace("c1", 10, "c"); if (!inserted) { // 通过it进行更新 }
问题1:try_emplace确实比find+insert更高效吗?
是的,try_emplace在效率上更优:
- find+insert的方式会两次遍历map:第一次
find查找键,第二次insert执行时会再次检查键是否存在,相当于重复了一次键值查找操作。 try_emplace只做一次遍历:它直接定位目标键的位置,键不存在则原地构造元素,存在则直接返回指向该元素的迭代器,避免了重复查找的开销。
此外,try_emplace能避免不必要的对象构造——如果键已存在,它不会构造st_A临时对象;而原insert写法会先构造st_A{10, "c"},哪怕最终因键存在插入失败,临时对象的构造和析构成本都会浪费。
问题2:嵌套mapmap<string, map<int, st_A>>如何正确使用try_emplace?
仍然适合用try_emplace,但需要分两步处理嵌套结构:
目标是插入pair{"c1", pair{1, st_A{10, "c"}}},即外层map键"c1"对应内层map,内层map键1对应st_A{10, "c"}。
正确实现如下:
map<string, map<int, st_A>> m2; // 第一步:处理外层map,获取或创建键"c1"对应的内层map auto [outer_it, outer_inserted] = m2.try_emplace("c1"); // outer_it->second 就是内层的map<int, st_A> // 第二步:向内层map插入元素,同样用try_emplace auto [inner_it, inner_inserted] = outer_it->second.try_emplace(1, 10, "c"); if (!inner_inserted) { // 如果内层元素已存在,通过inner_it更新 }
解释:
- 外层
try_emplace("c1")会在键"c1"不存在时,默认构造一个空的map<int, st_A>,无需额外参数。 - 拿到内层map后,再对它调用
try_emplace,传入内层键1和st_A的构造参数10, "c",就能原地构造目标元素,避免不必要的临时对象。
你之前尝试的m1.try_emplace("c1", 1, 10, "c")不合法,是因为外层map的值类型是map<int, st_A>,而传入的1,10,"c"无法匹配map<int, st_A>的构造函数,因此需要分两步操作嵌套结构。
内容的提问来源于stack exchange,提问作者f1msch
相关产品推荐
相关产品推荐

