含引用成员的类中显式默认的比较运算符为何被删除?
解答
一、默认比较运算符被删除的原因
C++标准明确规定:当类包含引用成员时,默认生成的operator<=>(三路比较运算符)和operator==会被隐式删除。
这个规则和拷贝/移动操作的禁用逻辑一致:默认特殊函数的设计原则是要么完全遵循成员的原始语义,要么不生成。引用的本质是对象的别名,其自身的比较逻辑是比较内存地址(判断是否指向同一对象),而非比较指向对象的内容。如果默认比较运算符自动解引用比较内容,会和用户对引用的直观认知产生歧义——用户可能想判断两个引用是否指向同一对象,而非对象内容是否相等。为了避免这种歧义,标准直接禁用了包含引用成员的类的默认比较运算符。
二、手动实现比较运算符的最简方式
只需手动解引用引用成员,直接比较指向的对象内容即可,以下是几种简洁写法:
1. 最简三路比较实现(推荐)
class Simple { public: Simple(const std::string& data) : data_(data) {} // 手动实现三路比较,编译器会自动生成==、!=、<、<=、>、>= auto operator<=>(const Simple& other) const { return data_ <=> other.data_; } private: const std::string& data_; };
根据C++20规则,显式定义operator<=>后,编译器会自动生成对应的operator==,无需额外编写。
2. 显式实现==和三路比较
如果需要更明确的控制,可以同时实现两者:
class Simple { public: Simple(const std::string& data) : data_(data) {} bool operator==(const Simple& other) const { return data_ == other.data_; } auto operator<=>(const Simple& other) const { return data_ <=> other.data_; } private: const std::string& data_; };
3. 一行式极简写法
甚至可以把三路比较写成一行:
auto operator<=>(const Simple& other) const { return data_ <=> other.data_; }
同样能让编译器自动生成所有必要的比较运算符。
内容的提问来源于stack exchange,提问作者mgr
相关产品推荐
相关产品推荐

