C++无自定义==运算符的结构体比较规则探究
问题解析与解答
1. 编译器查找operator==的逻辑
当比较两个未定义operator==的自定义类型对象时,编译器会按以下顺序寻找可用的相等运算符:
- 优先查找用户定义的
operator==(包括类成员、全局函数,以及通过ADL规则找到的相关运算符)。 - 若没有用户定义版本,尝试对两个操作数进行隐式类型转换,看能否转换到同一个支持相等比较的类型(比如内置类型、或已定义
operator==的自定义类型),转换成功后调用对应类型的比较运算符。 - 在C++20及以后标准中,若类是聚合类型、或所有成员都支持相等比较,编译器会自动合成默认的
operator==。
2. 示例中X、Y的差异原因
- Y类可编译:Y定义了
operator int()隐式转换运算符,编译器能将两个Y对象都转为int,进而调用内置的int == int运算符,因此编译通过。 - X类在旧标准下编译失败:X是聚合类型,但在C17及更早版本中,编译器不会自动合成
operator==;同时X没有任何隐式转换到其他可比较类型的逻辑,编译器找不到可用的相等运算符,因此报错。如果是C20及以后,编译器会为X合成默认的operator==,此时该行代码可正常编译。
3. 嵌套类场景的问题本质
嵌套类的逻辑和顶层类完全一致:如果嵌套类既没有自定义operator==,也没有能转换到可比较类型的隐式转换,同时不符合C++20默认合成运算符的条件(比如成员包含不支持相等比较的类型),就会编译失败。这不是嵌套类的特殊限制,而是没有满足比较的必要条件。
4. 是否仅适用于可转换为内置类型的情况?
不完全是,分版本讨论:
- C++17及更早:确实如此——要么有用户定义的
operator==,要么两个操作数能隐式转换到同一个支持相等比较的类型(不一定是内置类型,比如若存在自定义类型Z且Z定义了operator==,而你的结构体可隐式转为Z,也能使用Z的比较逻辑)。 - C++20及以后:除了隐式转换的情况,编译器会为满足条件的类自动合成默认
operator==,此时即使不能转换到内置类型,只要类的所有成员都支持相等比较,就能正常使用==。
C++20下X类的编译示例
struct X { int x; }; int main() { bool val {X{} == X{}}; // C++20及以后编译通过,编译器合成默认operator== }
内容的提问来源于stack exchange,提问作者user3882729
相关产品推荐
相关产品推荐

