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

标签 c++ performance std unordered-map

我对现代 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);
   }
}

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

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

  • try-catch 构造中调用 myMap.at()

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

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

最佳答案

你可以的

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

或使用新的 C++17 初始化语句语法

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

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

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

关于c++ - 检查 C++ std::unordered_map 中是否存在键的最有效范例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71171346/

相关文章:

C++使用分隔符逐行读取文件并将数据存储到变量中

c++ - 为什么 boost::timer 的结果如此奇怪?

c++ - 编译器错误 : expected primary-expression before '>' token

java - 加速 jasperreports

java - 为什么java后台进程很慢?

c++ - std::ofstream 无法在 win7/64 和 msvc2013 上使用 std::ios::ate 打开大文件

c++ - 在展开堆栈之前获取回溯

java - 在 java 中扫描非常大的文件的最快方法是什么?

c++ - 使用带有 std::array 作为参数的 std::make_shared 初始化 std::shared_ptr

c++ - std 没有成员 'getline' ?