繁体   English   中英

三向比较运算符与减法有何不同?

[英]How is the three-way comparison operator different from subtraction?

在C ++ 20中有一个新的比较运算符<=> 但是我认为在大多数情况下,简单的减法效果很好:

int my_strcmp(const char *a, const char *b) {
    while (*a == *b && *a != 0 && *b != 0) {
        a++, b++;
    }
    // Version 1
    return *a - *b;
    // Version 2
    return *a <=> *b;
    // Version 3
    return ((*a > *b) - (*a < *b));
}

它们具有相同的效果。 我无法理解其中的差异。

运算符解决了减法带来的数值溢出问题:如果从接近INT_MIN的负数中减去一个大的正数,则会得到一个不能表示为int ,从而导致未定义的行为。

虽然版本3没有这个问题,但它完全缺乏可读性:以前从未见过这个技巧的人需要一些时间才能理解。 <=>运算符也修复了可读性问题。

这只是新运营商解决的一个问题。 Herb Sutter的Consistent比较文件第2.2.3节讨论了<=>与其他数据类型的使用,其中减法可能会产生不一致的结果。

以下是减法不适用的一些情况:

  1. unsigned类型。
  2. 导致整数溢出的操作数。
  3. 用户定义的类型没有定义operator - (可能因为它没有意义 - 可以定义一个顺序而不定义距离的概念)。

我怀疑这份清单并非详尽无遗。

当然,至少可以为#1和#2提供变通方法。 但是operator <=>的意图是封装丑陋。

这里有一些有意义的答案,但Herb Sutter在他的论文中特别说:

<=>适用于类型实现者:在运算符<=>的实现之外的用户代码(包括通用代码)几乎不应该直接调用<=>(已经在其他语言中发现为良好实践);

因此,即使没有区别,运算符的要点也不同:帮助类编写者生成比较运算符。

减法运算符和“太空船”运算符之间的核心差异(根据Sutter的提议)是重载operator-给你一个减法运算符,而重载operator<=>

  • 为您提供6个核心比较运算符(即使您将运算符声明为default :无需编写代码!);
  • 声明您的班级是否具有可比性,是否可以排序,以及该订单是全部还是部分(Sutter提案中的强弱);
  • 允许异构比较:您可以重载它以将您的类与任何其他类型进行比较。

其他差异在于返回值: operator<=>将返回类的enum ,该类指定类型是否可排序以及排序是强还是弱。 返回值将转换为-1,0或1(尽管Sutter为返回类型留出空间以指示距离,如strcmp所做的那样)。 在任何情况下,假设-1,0,1返回值,我们最终将在C ++中获得真正的signum函数 signum(x) == x<=>0

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM