为什么赋值运算符和相等运算符之间没有 1:1 的关系?

Why no 1:1 relationship between assignment and equality operators?

本文关键字:关系 之间 赋值运算符 运算符 为什么      更新时间:2023-10-16

在下面的代码示例中,由于我比较了两个std::map对象,因此我不得不实现MyId::operator==()

MyId是一个简单的类:基本上是数组上的包装器。这让我想知道为什么强制要求使用相等运算符:为什么我们没有给出默认的按位比较器?毕竟,我们得到了一个默认的赋值运算符,它在对象之间执行按位成员复制。

我了解深拷贝和浅拷贝之间的区别,以及对赋值和相等运算符的需求。我的问题是,当有默认赋值时,为什么没有默认的"按位相等检查"?

#include <iostream>
#include <map>
#include <cstring>
typedef int myid[ 3 ];
struct MyId
{
myid id_;
bool operator<( const struct MyId& other ) const { return this < &other; }
bool operator==( const struct MyId& other ) const
{
return ( 0 == std::memcmp( id_, other.id_, sizeof( myid ) ));
}
};
int main( int argc, char* argv[] )
{
std::map< MyId, int> map;
MyId id = { 1, 2, 3 };
map[ id ] = 5;
std::map< MyId, int> map2;
map2[ id ] = 5;
// This forces implementation of MyId::operator==():
std::cout << std::boolalpha <<( map == map2 ) << std::endl;
MyId i1 = { 4, 5, 6 };
MyId i2 = { 7, 8, 9 };
// No required implementation of MyId::operator=():
i1 = i2;
return 0;
}

更新:公开纠正了我的脑屁 RE:按位与按成员默认赋值运算符。

毕竟,我们得到了一个默认的赋值运算符,它执行 对象之间的按位复制。

不,它没有。相反,默认的复制赋值运算符是以复制分配对象的每个成员的方式构造的。根据复制赋值运算符在字段类型中的实现方式,结果可能远非按位复制。

无论如何,默认的复制分配(或复制构造,或移动分配,甚至销毁)行为的设计方式是为了满足常见的基本需求。根据语言规范,它在大多数情况下都可用,但在某些情况下,语言不确定您的语义,并且需要对这些进行显式定义。

相等运算符不同。实际的相等关系不是由语言语法隐含的,而是由语义隐含的。编译器不知道你如何看待一个类的两个实例"相等"——因此它要求你告诉他。