【问题标题】:performance of declaring objects声明对象的性能
【发布时间】:2021-01-02 23:33:26
【问题描述】:

当我在如下循环中声明地图时,我在某种大学征服中进行编码并注意到了一些事情:

for (int i = 0; i < n; i++)
{
    map<int, bool> hashMap;
    //...
}

花费的时间比:

map<int, bool> hashMap;
for (int i = 0; i < n; i++)
{
    hashMap.clear();
    //...
}

所以我想知道为什么在循环中声明一个对象比重新初始化它的性能更差?

【问题讨论】:

    标签: c++ performance std c++-standard-library


    【解决方案1】:

    在代码的第一个版本中,hashMap 的构造函数和析构函数被调用n 次,而在第二个版本中它们只被调用一次。

    自然的问题是为什么破坏和构造一个新的map 对象与清除和重用一个相同的对象会有明显的不同。这只能通过检查正在使用的实现的实际map 代码来明确回答,因此以下只是一个合理的猜测。

    std::map 通常使用red-black trees 实现,红黑树实现通常使用sentinel 节点作为NIL 叶,例如Benefit of a sentinel node in a red black tree?。每次构建树时都必须分配这个哨兵,然后在销毁时释放。相反,clear'ing a map 会清空树,但会重用关联的内部对象。

    对于此类实现的真实示例,Microsoft 的 _Tree 构造函数调用了恰当命名的 _Alloc_sentinel_and_proxy();。由于它们的 map 派生自 _Tree,因此每次构造 map 对象时都会调用它。

    【讨论】:

    • 转储程序集并将构造开销与破坏开销进行比较会很有趣。我怀疑,没有做过比较,施工开销可能是两者中较大的几倍。将其置于循环内的累积效应只会使问题更加复杂。
    • @DavidC.Rankin 顺便说一句,我希望更重要的部分是关于内存操作,实际上,分配的成本高于释放。
    猜你喜欢
    • 1970-01-01
    • 2011-05-13
    • 2011-01-13
    • 1970-01-01
    • 1970-01-01
    • 2020-12-29
    • 1970-01-01
    • 1970-01-01
    • 2013-07-14
    相关资源
    最近更新 更多