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

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

在下面的代码示例中,因为我比较两个 std::map 对象,所以我不得不实现 MyId::operator==().

MyId 是一个简单的 class:基本上是对数组的包装。这让我想知道为什么必须使用相等运算符:为什么我们不提供默认的按位比较器?毕竟,我们有一个默认的赋值运算符,它在对象之间进行按位成员复制。

我了解深拷贝和浅拷贝之间的区别以及需要 赋值和相等运算符。我的问题是为什么有默认分配时没有默认 "bitwise equality check"?

#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;
}

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

After all, we are given a default assignment operator, which does a bitwise copy between objects.

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

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

相等运算符不同。实际的相等关系不是由语言语法暗示的,而是纯粹由语义暗示的。编译器不知道您如何看到 class 'equal' 的两个实例 - 因此它要求您告诉他。