Unordered_map后面是emplace还是只是插入以获得最大效率?

时间:2014-12-28 19:24:02

标签: c++ performance insert unordered-map

所以我一直在研究不同的unordered_map函数调用的排序效率。以下是同一代码中的两种可能的工作方式。

注意:keywordMap是一个无序映射,它将字符串映射到自制结构的向量(这是e的类型)。这是在循环中完成的。

第一个选项:

auto curKeyWord = someString;
auto curEntryPair = keywordMap.insert(
     make_pair( move(curKeyWord), vector<entry*>{e} ) );
if (!curEntryPair.second){//insertion failed
       curEntryPair.first->second.push_back(e);
    }

第二个选项:

auto curKeyWord = someString;
auto curEntry = keywordMap.find(curKeyWord);
if( curEntry == end(keywordMap) ){//DNE in map
    keywordMap.emplace( make_pair( move(curKeyWord), vector<entry*>{e} ) );
}
else{
    curEntry->second.push_back(e);
}

我对哪些代码块更快感兴趣。问题实际上归结为.insert的工作原理。如果insert基本上用作查找键应该在哪里并且如果它不存在则插入它,那么第一个应该更快,因为它只是一个探测器。一旦我调用了insert,如果插入没有做任何事情,我就需要调用push_back。然而,这也是非常丑陋的。我也很好奇,如果插入具有相同的问题,那么它在检查地图中是否存在密钥之前构造元素。

我可能需要对这两段代码进行基准测试,但我想知道是否有任何我想念的信息会告诉我现在的答案。

1 个答案:

答案 0 :(得分:0)

一般来说,第一位代码更快,因为它执行单一查找。

以下是在map中执行插入/覆盖的常用方法:

auto rv = map.insert(std::make_pair(key, value));
if (!rv.second)
    rv.first->second = value;

这里的要点是std::map通常实现为平衡二叉树(谷歌:红/黑树),因此insert()find()都取O(log(n) ) 脚步。 IE容器具有自然的内部订单,插入必须将新项目放在正确的位置。 (这就是密钥必须严格按顺序排列的原因。)

std::unordered_map使用散列,因此对于默认构造的映射,查找为O(1)(即每个桶中只有一个项目)。一旦允许冲突(即每个桶中有k个项目),每次查找都需要O(k)步。

现在,回到最初的问题 - 做更少的工作总是更好。 std :: unordered_map情况的差异非常小(第二次查找在默认情况下以O(1)步骤发生)。