我知道STL关联容器(以及我猜想要排序的其他容器)使用排序标准来测试是否相等。
容器的排序标准默认为st :: less,这样就可以对容器进行相等测试:
if (! (lhs < rhs || rhs < lhs))
或类似的东西。我有几个问题......
首先,它似乎是一种比较平等的奇怪低效方式 - 为什么STL会这样做?我原本期望STL容器只需要一个额外的默认参数来代替。
我的第二个问题更多是关于对上述if语句的评估。在C ++中,将评估该语句的多少(lhs&gt; rhs)是真的?它会在评估失败的一方后停止尝试,从而节省一些效率吗?如果是,那么首先评估表达式的哪一部分?
答案 0 :(得分:18)
在“有效STL”中,Scott Meyers在第19项中对此进行了广泛的讨论:
正如您所料,了解平等和等同之间的区别。
Equality 基于operator==
。
Equivalence “基于排序范围内对象值的相对排序...如果c
中的两个对象在{{1}中都不在另一个之前,则它们具有等价值排序顺序。“
c
然后迈耶斯重申:
这是有道理的:两个值是等价的(相对于某些值而言) 订购标准)如果两者都不在另一个之前(根据那个 准则。)
至于为什么STL会这样做:
仅使用单一比较功能并使用 等价作为“相同”的意思的仲裁者 标准的关联容器......避免那种混乱 会产生于平等和等同的混合使用 标准关联容器。
阅读第19项(涵盖6页的大部分内容),让自己获得完整的味道。
答案 1 :(得分:5)
STL关联容器
您的意思是:标准C ++排序的关联容器。
我原本期望STL容器只取一个额外的默认参数来代替。
会实现什么?在您的教科书红黑树算法中,而不是
if (x < y)
// ...
else if (y < x)
// ...
else
// equality
你有
if (x == y)
// equality
else if (x < y)
// ...
else
// y < x
在最坏的情况下仍然进行两次比较。
回应对这个答案的评论:只提供一个小于运算符使容器更容易使用,因为不需要保持小于和等于之间的一致性。让我们假设您有一个存储浮点数的程序。有一天,有人决定替换按位相等float_equals
函数,它恰好被某个容器使用,但也被它们的代码使用,通过近似比较。如果该人没有更新float_less
函数,因为他们的代码不使用该函数,那么您的容器代码会神秘地破坏。
(哦,在所示的示例代码中,一如既往地应用短路。)
答案 2 :(得分:3)
关于第二个问题:适用于布尔表达式的标准C延迟评估规则。如果||
的LHS为真,则不评估RHS。
答案 3 :(得分:0)
C ++使用||评估if()从左到右的情况。评估左侧(lhs&lt; rhs) - 如果它是真的并且它不是复合语句(它不在你的情况下),它会在不检查右侧的情况下评估整数if是否为真。 (然后确实返回否定的值,因为它没有在它前面。)如果它是假的,那么它移动到右侧(rhs&lt; lhs)并评估它然后整个表达式。
答案 4 :(得分:-2)
首先,它似乎是比较平等的一种奇怪的低效方式
是的,但已排序的容器相对很少进行此测试。
使用像strcmp
这样的比较功能会更好。使用less-than和compare会更好。
在C ++中,将评估该语句的多少(lhs&gt; rhs)是真的?
在C和C ++中,a && b
,a || b
,a, b
,a ? b : c
从左到右进行评估,只评估有用的权利部分(除了C ++中重载 &&
,||
,,
运算符。)
这允许一些有用的简短测试,例如:p != NULL && *p > 2