其他分享
首页 > 其他分享> > c – 为什么使用std :: less作为比较std :: map和std :: set中的键的默认函子?

c – 为什么使用std :: less作为比较std :: map和std :: set中的键的默认函子?

作者:互联网

我想知道为什么std :: map和std :: set使用std :: less作为比较键的默认函子.为什么不使用类似于strcmp的仿函数?就像是:

  template <typename T> struct compare
  {
     // Return less than 0 if lhs < rhs
     // Return 0 if lhs == rhs
     // Return greater than 0 if lhs > rhs
     int operator()(T const& lhs, T const& rhs)
     {
        return (lhs-rhs);
     }
  }

假设地图中有两个对象,其中键为key1和key2.现在我们要插入另一个带键key3的对象.

当使用std :: less时,insert函数需要首先使用key1和key3调用std :: less :: operator().假设std :: less :: operator()(key1,key3)返回false.它必须使用切换的键,std :: less :: operator()(key3,key1)再次调用std :: less :: operator()来判断key1是否等于key3或key3是否大于key1.如果第一个调用返回false,则有两个调用std :: less :: operator()来做出决定.

如果使用std :: map :: insert进行比较,那么只需一次调用即可获得足够的信息来做出正确的决定.

根据map中键的类型,std :: less :: operator()(key1,key2)可能很昂贵.

除非我遗漏了一些非常基本的东西,否则std :: map和std :: set应该使用比较而不是std :: less作为比较键的默认算符?

解决方法:

我决定问Alexander Stepanov(STL的设计师).我被允许引用他如下:

Originally, I proposed 3-way comparisons. The standard committee asked
me to change to standard comparison operators. I did what I was told.
I have been advocating adding 3-way components to the standard for
over 20 years.

但请注意,也许不直观,双向并不是一个巨大的开销.您不必进行两倍的比较.在向下的每个节点上只有一个比较(没有相等检查).成本无法提前返回(当密钥处于非叶子时)和最后一个额外的比较(交换参数以检查相等性).如果我没有弄错的话,那就是

1 + 1/2*1 + 1/4*2 + 1/8*3 + ...
= 1 + 1/2+1/4+1/8+... + 1/4+1/8+... + ...
-> 3  (depth -> infty)

在包含查询元素的平衡树上平均进行额外比较.

另一方面,3路比较没有可怕的开销:Branchless 3-way integer comparison.现在,在每个节点检查比较结果与0(相等)的额外分支是否比在最后支付~3额外比较的开销更少题.可能并不重要.但我认为比较本身应该是3值的,因此可以改变是否使用所有3种结果的决定.

更新:请参阅下面的评论,了解为什么我认为3-way比较在树中更好,但不一定在平面阵列中.

标签:stdset,c,stdmap
来源: https://codeday.me/bug/20191001/1840215.html