C++ std::unordered_map::clear()做什么?

C++ std::unordered_map::clear()做什么?,c++,std,unordered-map,C++,Std,Unordered Map,我有一段简单的代码: #pragma GCC optimize ("O0") #include <unordered_map> int main() { std::unordered_map<int, int> map; static constexpr const int MaxN = 2e6 + 69; map.reserve(MaxN); int t = 1000; while

我有一段简单的代码:

#pragma GCC optimize ("O0")
#include <unordered_map>
int main()
{
    std::unordered_map<int, int> map;
        
    static constexpr const int MaxN = 2e6 + 69;
    map.reserve(MaxN);
    
    int t = 1000;
    while (t--)
    {
        map.clear();
    }
    
    return 0;
}
我的代码的输出是:

8579908 bytes allocated.
I'm constructed from pointer: 0xd09020
1000 clear() runs take 1139 milliseconds.
I'm constructed from pointer: 0xd09020
8579908 bytes deallocated.
Deleted 0xd09020
Address 0xd09020 accessed 1 times.
似乎在
reserve()
语句中分配了一次巨大的内存块,在映射超出范围时释放一次,就像我所期望的那样。而且,指针只被访问一次


那么为什么1000
std::unordered\u map::clear()
操作需要这么多时间呢?GCC的实现在这里做了什么?

对于无序关联容器,
保留(N)
的定义是,它分配足够的存储桶,以便在容器中存在
N
元素时,表的负载因子小于或等于最大负载因子。最大负载系数的默认值为1,因此
reserve
必须分配至少2000069个桶

确实,
clear()
被指定为需要线性时间,复杂性要求是根据容器中元素的数量。但更准确地说:复杂性要求指定了容器元素上的操作数。例如,如果一个容器包含1个元素,那么当调用
clear()
时,容器可以对该元素执行的操作数必须有一个恒定的上限。但是,除了这些操作之外,容器可以在“记账”上花费的时间没有限制。因此,基于散列的容器的
clear()
很可能需要额外的时间,而不会违反标准


我看了看桌子。它遍历所有元素并销毁它们,然后使用
memset
将所有bucket指针重置为null。因此,事实上,桶数的线性化总是需要额外的时间,即使这是“不必要的”,因为首先没有元素。因此,您的程序的1000次
clear()
迭代将使用这种实现执行至少2000069000次操作(假设一个指针大小的内存位置为零需要一次操作)。

请说明如何测量各种操作所花费的时间——我在显示的代码中没有看到任何内容。还要注意,测量未优化代码的性能在很大程度上是毫无意义的。删除
#pragma GCC optimize(“O0”)
指令。我想
reserve
可能占用了大部分时间。您尝试过调试吗?还可以看到,在禁用优化的情况下,您无法可靠地评测任何内容……您是在测试优化的构建还是未优化的调试构建?未优化的版本(大多数编译器的默认版本)只关心生成易于调试的代码,性能是次要的,而调试版本的速度非常慢,并且做了许多优化器通常只删除的事情。如果您想知道您的代码在现实世界中的执行情况,请始终测试优化的构建。为未优化的调试构建计时是浪费时间。“#pragma GCC optimize(“O0”)”似乎指向了一种奇怪的、非标准的、确保非优化构建的方式。
8579908 bytes allocated.
I'm constructed from pointer: 0xd09020
1000 clear() runs take 1139 milliseconds.
I'm constructed from pointer: 0xd09020
8579908 bytes deallocated.
Deleted 0xd09020
Address 0xd09020 accessed 1 times.