检查 c++ std::unordered_map 中是否存在键的最有效范例?

Col*_*ole 3 c++ performance unordered-map std

我对现代 C++ 比较陌生,并且使用外国代码库。有一个函数接受 std::unordered_map 并检查映射中是否存在键。代码大致如下

uint32_t getId(std::unordered_map<uint32_t, uint32_t> &myMap, uint32_t id) 
{
   if(myMap.contains(id))
   {
     return myMap.at(id);
   }
   else
   {
     std::cerr << "\n\n\nOut of Range error for map: "<< id << "\t not found" << std::flush;
     exit(74);
   }
}
Run Code Online (Sandbox Code Playgroud)

似乎调用contains()后面的at()效率很低,因为它需要双重查找。所以,我的问题是,实现这一目标最有效的方法是什么?我还有一个后续问题:假设地图相当大(~60k 元素)并且此方法被频繁调用,上述方法有多大问题?

经过一番搜索,似乎以下范例比上面的更有效,但我不确定哪个是最好的。

  • 在构造myMap.at()内部调用try-catch

    • 优点:at如果键不存在,会自动抛出错误
    • 缺点:try-catch显然成本相当高,并且还限制了优化器可以对代码执行的操作
  • 使用find

    • 优点:一次调用,无try-catch开销
    • 缺点:涉及使用迭代器;比仅仅返回值有更多的开销
    auto findit = myMap.find(id);
    if(findit == myMap.end())
    {
      //error message;
      exit(74); 
    }
    else
    {
      return findit->first;
    }
Run Code Online (Sandbox Code Playgroud)

Jak*_*ark 8

你可以做

// stuff before
{
    auto findit = myMap.find(id);
    if ( findit != myMap.end() ) {
        return findit->first;
    } else {
       exit(74);
    }
}
// stuff after
Run Code Online (Sandbox Code Playgroud)

或使用新的 C++17 init 语句语法

// stuff before
if ( auto findit = myMap.find(id); findit != myMap.end() ) {
    return findit->first;
} else {
   exit(74);
}
// stuff after
Run Code Online (Sandbox Code Playgroud)

两者都仅在本地范围内定义迭代器引用。由于交互器的使用已经得到了最明确的优化,所以我会选择它。几乎可以肯定,进行第二次哈希计算会变慢。

另请注意,findit->first返回而不是。我不确定您期望代码做什么,但问题中的代码片段之一返回值,而另一个代码片段返回键