Там новый оператор сравнения <=>
в С ++ 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 свободна от этой проблемы, ей совершенно не хватает читабельности: потребуется время, чтобы понять тот, кто никогда раньше не видел этот трюк. <=>
Оператор также исправляет проблему читабельности.
Это только одна проблема, решаемая новым оператором. Раздел 2.2.3 из Херб Саттерс Последовательное сравнение бумага говорит об использовании <=>
с другими типами данных языка, где вычитание может привести к противоречивым результатам.
Вот некоторые случаи, когда вычитание не будет работать для:
unsigned
типы.operator -
(возможно, потому что это не имеет смысла — можно определить порядок, не определяя понятие расстояния).Я подозреваю, что этот список не является исчерпывающим.
Конечно, можно найти обходные пути как минимум для № 1 и № 2. Но намерение operator <=>
это заключить в капсулу это уродство.
Здесь есть несколько значимых ответов о разнице, но Херб Саттер в его бумага конкретно говорит:
<=> для разработчиков типов: код пользователя (включая универсальный код) вне реализации оператора<=> почти никогда не должен вызывать <=> напрямую (как уже было обнаружено в качестве хорошей практики на других языках);
Таким образом, даже если бы не было никакой разницы, смысл оператора в другом: помочь авторам классов генерировать операторы сравнения.
Основное различие между оператором вычитания и оператором «космического корабля» (согласно предложению Саттера) состоит в том, что перегрузка operator-
дает вам оператор вычитания, тогда как перегрузка operator<=>
:
default
: нет кода для записи!);Другие различия в возвращаемом значении: operator<=>
вернет enum
класса указывает, является ли тип сортируемым и является ли сортировка сильной или слабой. Возвращаемое значение будет преобразовано в -1, 0 или 1 (хотя Саттер оставляет место для возвращаемого типа, чтобы также указать расстояние, как strcmp
делает). В любом случае, принимая значение -1, 0, 1, мы, наконец, получим настоящая функция signum в C ++! (signum(x) == x<=>0
)