c++ - 为什么在unordered_map中使用find()比直接读取要快很多?

标签 c++

这很难描述,所以我只展示代码:

#include <bits/stdc++.h> 
using namespace std; 

int main() 
{ 
    clock_t start, end; 
    unordered_map<int, int> m;
    long test=0;
    int size = 9999999;
    for (int i=0; i<size/3; i++) {
        m[i] = 1;
    }
    start = clock(); 
    for (int i=0; i<size; i++) {
        //if (m.find(i) != m.end())
            test += m[i];
    }
    end = clock(); 
    double time_taken = double(end - start) / double(CLOCKS_PER_SEC); 
    cout << "Time taken by program is : " << fixed  
         << time_taken << setprecision(5); 
    cout << " sec " << endl; 
    return 0; 
} 

结果(3次): 没有 if (m.find(i) != m.end()):

Time taken by program is : 3.508257 sec 
Time taken by program is : 3.554726 sec 
Time taken by program is : 3.520102 sec 

if (m.find(i) != m.end()):

Time taken by program is : 1.734134 sec 
Time taken by program is : 1.663341 sec 
Time taken by program is : 1.736100 sec 

谁能解释一下为什么?当 key 没有出现时,add m[i] 到底发生了什么?

最佳答案

在这一行

test += m[i];

operator[] 做两件事:首先它尝试找到给定键的条目,然后如果该条目不存在则创建一个新条目。

另一方面:

if (m.find(i) != m.end())
        test += m[i];

operator[] 只做一件事:它找到具有给定键的元素(并且因为您之前检查过它存在,所以不必构造新条目)。

由于映射仅包含最大 size/3 的键,您的结果表明创建元素的开销超过了首先检查元素是否存在的开销。

在第一种情况下, map 中有 size 元素,而在第二种情况下, map 中只有 size/3 元素。 请注意,映射中的元素越多,调用 operator[] 的开销就越大。是Average case: constant, worst case: linear in size. find 也是如此。但是,多次调用这些方法,最坏的情况应该分期偿还,剩下的就是平均常量。

感谢 Aconcagua 指出您没有在 map 中预留空间。在第一种情况下,您添加了许多需要分配空间的元素,而在第二种情况下, map 的大小在您测量的部分期间保持不变。尝试在循环之前调用 reserve。我天真地希望在那种情况下循环会非常相似。

关于c++ - 为什么在unordered_map中使用find()比直接读取要快很多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56575799/

相关文章:

c++ - kiss_fftr 后接 kiss_fftri(窗口尺寸非常大)不返回输入信号

c++ - PlatformToolset 和 "deleted function"错误 (C2280)

c++ - move 语义和对象类型参数

c++ - 成员函数指针转换

c++ - 编译 C 代码,看不到 #define 常量

c++ - 在函数调用时获取堆栈溢出

c++ - 如何将 QString 转换为特定格式的 QDate?

c++ - Clang scan-build 将 CXX 编译器识别为 GNU 9.1.0,而不是 clang

c++ - 如何判断多维数组中的元素是否为空

c++ - 在不连接按钮的情况下手动关闭 Modal QDialog - 代码完成后对话框挂起