- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我想知道为什么 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);
}
}
假设一个 map
里面有两个对象,键是 key1
和 key2
。现在我们要插入另一个带有 key3
键的对象。
使用std::less
时,insert
函数需要先用调用
和 std::less::operator()
>key1key3
。假设 std::less::operator()(key1, key3)
返回 false。它必须再次调用 std::less::operator()
并切换键,std::less::operator()(key3, key1)
来决定key1
是否等于 key3
或 key3
是否大于 key1
。有两次调用 std::less::operator()
来判断第一次调用是否返回 false。
如果 std::map::insert
使用了 compare
,那么只需一次调用即可获得足够的信息来做出正确的决定。
根据 map 中键的类型,std::less::operator()(key1, key2)
可能很昂贵。
除非我遗漏了一些非常基本的东西,否则 std::map
和 std::set
不应该使用类似 compare
的东西而不是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.
但请注意,也许不直观,2-way 并不是一个巨大的开销。 您不必进行两倍的比较。 在下降过程中每个节点只进行一次比较(无相等性检查)。代价是不能及早返回(当 key 在非叶子中时)和最后一次额外的比较(交换参数以检查相等性)。如果我没记错的话,那就是
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 路比较在树中更好,但不一定在平面数组中。
关于c++ - 为什么使用 std::less 作为默认仿函数来比较 std::map 和 std::set 中的键?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22308437/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!