I'm learning about operator overloading in C++, and I see that == and != are simply some special functions which can be customized for user-defined types. My concern is, though, why are there two separate definitions needed? I thought that if a == b is true, then a != b is automatically false, and vice versa, and there is no other possibility, because, by definition, a != b is !(a == b). And I couldn't imagine any situation in which this wasn't true. But perhaps my imagination is limited or I am ignorant of something?

我知道我可以用一个定义另一个,但这不是我要问的。我也没有问通过值和单位来比较对象之间的区别。或者两个对象是否可以同时相等和不相等(这绝对不是一个选项!这些事情是相互排斥的)。我想问的是:

有没有可能在这种情况下,问两个对象是否相等的问题是有意义的,但问它们不相等的问题是没有意义的?(无论是从用户的角度,还是从实现者的角度)

如果没有这种可能性,那么究竟为什么c++将这两个操作符定义为两个不同的函数呢?


当前回答

我只回答你问题的第二部分,即:

如果没有这种可能性,那么究竟为什么c++将这两个操作符定义为两个不同的函数呢?

允许开发人员重载两者是有意义的一个原因是性能。您可以通过同时实现==和!=来允许优化。那么x != y可能比!(x == y)便宜。一些编译器可能能够为您优化它,但也可能不能,特别是当您有涉及大量分支的复杂对象时。

即使在Haskell中,开发人员非常重视法律和数学概念,仍然允许重载==和/=,正如您可以在这里看到的(http://hackage.haskell.org/package/base-4.9.0.0/docs/Prelude.html#v:-61--61-):

$ ghci
GHCi, version 7.10.2: http://www.haskell.org/ghc/  :? for help
λ> :i Eq
class Eq a where
  (==) :: a -> a -> Bool
  (/=) :: a -> a -> Bool
        -- Defined in `GHC.Classes'

这可能被认为是微观优化,但在某些情况下可能是合理的。

其他回答

有没有可能的情况是问关于二的问题 对象相等是有意义的,但是问它们不相等 相等没有意义吗?(无论是从用户的角度,还是从 实现者的角度)

这只是个人观点。也许不是。但是语言的设计者并不是无所不知的,他们决定不限制那些可能想出有意义的情况的人(至少对他们来说)。

我只回答你问题的第二部分,即:

如果没有这种可能性,那么究竟为什么c++将这两个操作符定义为两个不同的函数呢?

允许开发人员重载两者是有意义的一个原因是性能。您可以通过同时实现==和!=来允许优化。那么x != y可能比!(x == y)便宜。一些编译器可能能够为您优化它,但也可能不能,特别是当您有涉及大量分支的复杂对象时。

即使在Haskell中,开发人员非常重视法律和数学概念,仍然允许重载==和/=,正如您可以在这里看到的(http://hackage.haskell.org/package/base-4.9.0.0/docs/Prelude.html#v:-61--61-):

$ ghci
GHCi, version 7.10.2: http://www.haskell.org/ghc/  :? for help
λ> :i Eq
class Eq a where
  (==) :: a -> a -> Bool
  (/=) :: a -> a -> Bool
        -- Defined in `GHC.Classes'

这可能被认为是微观优化,但在某些情况下可能是合理的。

最后,使用这些操作符检查表达式a == b或a != b是否返回布尔值(true或false)。这些表达式在比较后返回一个布尔值,而不是互斥的。

(. .为什么需要两个不同的定义?

需要考虑的一件事是,实现其中一个操作符可能比仅使用另一个操作符的反求值更有效。

(我这里的例子是垃圾,但重点仍然成立,想想bloom过滤器,例如:它们允许快速测试,如果某些东西不在集合中,但测试它是否在集合中可能需要更多时间。)

(. .根据定义,a != b是!(a == b)。

这是你作为程序员的责任。这可能是编写测试的好方法。

作为对编辑的回应;

也就是说,如果某些类型可能具有操作符==而没有!=,或者反之亦然,以及在什么情况下这样做有意义。

一般来说,不,这说不通。相等运算符和关系运算符通常是集合。如果存在平等,那么也存在不平等;小于,然后大于,以此类推,使用<= etc。类似的方法也应用于算术运算符,它们通常也是自然逻辑集。

这在std::rel_ops命名空间中得到了证明。如果实现了相等操作符和小于操作符,则使用该名称空间将提供其他名称,这些名称空间是根据原始实现的操作符实现的。

话虽如此,在某些条件或情况下,其中一个并不立即意味着另一个,或者不能在其他方面得到实施?是的,有,可以说很少,但它们确实存在;同样,正如rel_ops是它自己的名称空间所证明的那样。出于这个原因,允许它们独立实现可以让您利用语言来获得所需的语义,或者以一种对代码的用户或客户端来说仍然自然和直观的方式获得所需的语义。

前面提到的惰性求值就是一个很好的例子。另一个很好的例子是,给他们不等于或不等于的语义。一个类似的例子是位移位操作符<<和>>用于流插入和提取。虽然在一般的圈子里它可能会引起不满,但在某些特定领域它可能是有意义的。