在C++20中,引入了一个新的运算符,称为“三路比较操作符”或“太空船操作符”,其符号为 <=>。这个运算符是C++20中的一个重要特性,提供了一种简化两个对象比较的方法。
三路比较操作符返回一个标准库类型std::strong_ordering(默认类型)、std::weak_ordering或std::partial_ordering的实例,这取决于参与比较的对象类型的属性。这个运算符基本上可以告诉你两个值是相等的、第一个值小于第二个值,还是第一个值大于第二个值。
这个操作符的行为类似于以下的组合:
- 如果a < b,则返回一个表示"小于"的值。
- 如果a > b,则返回一个表示"大于"的值。
- 如果a == b,则返回一个表示"等于"的值。
比如:
#include <compare>
auto result = a <=> b;
if (result < 0) {
// a 小于 b
std::cout << "a < b" <<std::endl;
} else if (result > 0) {
// a 大于 b
std::cout << "a > b" <<std::endl;
} else {
// a 等于 b
std::cout << "a = b" <<std::endl;
}
这种新的比较方法简化了类的排序和比较逻辑的实现,因为你只需要定义一种比较方式,而不是像以前那样分别定义 <、> 和 ==。
让我们以如下例子对比传统的比较方法和C++20中引入的三路比较操作符(太空船操作符):
传统比较方法
在C++20之前,如果你想要在自定义类型上实现比较操作(如<, >, ==),你需要分别为每个操作符提供实现。例如,对于一个简单的Point类,它可能看起来是这样的:
class Point {
public:
int x, y;
bool operator==(const Point& other) const {
return x == other.x && y == other.y;
}
bool operator<(const Point& other) const {
return x < other.x || (x == other.x && y < other.y);
}
bool operator>(const Point& other) const {
return other < *this;
}
// 可能还需要其他比较操作符...
};
使用三路比较操作符
C++20引入了三路比较操作符<=>,它允许你通过单一的函数实现所有标准比较。使用这个操作符,上面的Point类可以这样简化:
#include <compare>
class Point {
public:
int x, y; //编译器按照字段声明的顺序进行比较,auto推导为 strong_ordering
auto operator<=>(const Point& other) const = default;
};
在这个例子中,我们只定义了一个操作符<=>,编译器将为我们生成所有必要的比较操作符(<, <=, >, >=, ==, !=)。我们使用= default来让编译器自动生成标准的比较逻辑。
可以从 cpp insight 看看编译器干了啥:
#include <compare>
class Point
{
public:
int x;
int y;
inline constexpr std::strong_ordering operator<=>(const Point & other) const /* noexcept */ = default;
inline constexpr bool operator==(const Point & other) const /* noexcept */ = default;
};
对比
-
简洁性:使用三路比较操作符可以显著减少代码量。你只需要一个操作符定义,而不是为每个比较操作写单独的函数。
-
错误减少:当你手动实现多个比较操作符时,可能会引入错误或不一致。使用三路比较操作符可以降低这种风险。
-
维护性:如果比较逻辑改变,使用三路比较操作符的代码只需在一个地方进行修改,而传统方法可能需要修改多处。
-
性能:在某些情况下,使用三路比较操作符可能提供更优的性能,因为编译器可以更有效地优化比较操作。
总的来说,三路比较操作符是C++20中一个强大且有用的特性,它简化了比较逻辑的实现,使代码更加清晰和易于维护。
打赏作者