如果可能,标准::映射分配是否静态

Is std::map allocation static when possible?

本文关键字:映射 分配 是否 静态 标准 如果      更新时间:2023-10-16

考虑具有相同效果的 3 个版本的代码:

版本1:

int main()  {
    std::map<int,int> x = {{0,0}, {1,1}, {2,2}};
    // Do some stuff...
    return 0;
}

版本2:

int main()  {
    std::map<int,int> x;
    x[0] = 0;
    x[1] = 1;
    x[2] = 2;
    // Do some stuff...
    return 0;
}

版本3:

int main()  {
    std::map<int,int> x;
    x.insert(std::pair<int,int>(0,0));
    x.insert(std::pair<int,int>(1,1));
    x.insert(std::pair<int,int>(2,2));
    // Do some stuff...
    return 0;
}

这些代码的效率如何?

我认为版本 1 是完全静态的分配:x所需的空间分配一次并设置值。我还认为版本 3 需要动态分配:每次调用插入都会检查键是否尚未使用,检查插入位置并在分配值之前分配更多空间进行映射。对于版本 2,我不确定。你能帮我吗?

C++标准对分配是在编译时还是运行时进行没有要求。所有这些都意味着实现可以自由地进行自己的优化(或不进行(。

因此,正确的做法是进行测试。

很可能尚未实施此类优化。没有std::mapconstexpr构造函数,尽管您在此处创建的std::initializer_list可能是编译时常量(请注意,这里也没有执行聚合初始化(

std::map<int,int> x = {{0,0}, {1,1}, {2,2}};

虽然它的实现是定义的,但std::map的分配从来都不是静态的。它使用 RB 树作为100例中99例的底层数据结构。
在您的情况下,在所有三种情况下,您具有完全相同的时间和空间复杂性。

经过所有这些猜测,我终于分析了代码。为此,我生成了 3 个代码,就像问题中一样,但有 100,000 个条目。以下是使用g++编译的多次运行平均值的结果,没有优化:

  • 版本 1:26 毫秒(编译时间:2.5 秒(
  • 版本 2:80 毫秒(编译时间:10 秒(
  • 版本 3:73 毫秒(编译时间:37 秒(

很明显,最好的解决方案是第一个。版本 2 和 3 在执行时几乎是等效的,但版本 3 在编译时确实更糟。