关联容器(STL)中的平等评估

时间:2011-11-21 19:44:20

标签: c++ stl

我知道STL关联容器(以及我猜想要排序的其他容器)使用排序标准来测试是否相等。

容器的排序标准默认为st :: less,这样就可以对容器进行相等测试:

if (! (lhs < rhs || rhs < lhs))

或类似的东西。我有几个问题......

首先,它似乎是一种比较平等的奇怪低效方式 - 为什么STL会这样做?我原本期望STL容器只需要一个额外的默认参数来代替。

我的第二个问题更多是关于对上述if语句的评估。在C ++中,将评估该语句的多少(lhs&gt; rhs)是真的?它会在评估失败的一方后停止尝试,从而节省一些效率吗?如果是,那么首先评估表达式的哪一部分?

5 个答案:

答案 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 && ba || ba, ba ? b : c从左到右进行评估,只评估有用的权利部分(除了C ++中重载 &&||,运算符。)

这允许一些有用的简短测试,例如:p != NULL && *p > 2