【问题标题】:Why no 1:1 relationship between assignment and equality operators?为什么赋值运算符和相等运算符之间没有 1:1 的关系?
【发布时间】:2017-10-26 18:53:51
【问题描述】:

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

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

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

#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:按位与按成员默认赋值运算符。

【问题讨论】:

  • 赋值运算符和复制构造函数进行成员复制 - 不是按位复制。

标签: c++ operator-overloading assignment-operator equality-operator


【解决方案1】:

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

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

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

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

【讨论】:

  • " 默认的复制赋值运算符的构造方式是复制分配对象的每个成员" 你是对的。我的脑袋放屁。
  • @StoneThrow 我的意思不是指出你的错误,但我实际上是在回答你的问题 :)
  • @iehrlick 明白了,我很尴尬,因为我在发布问题时不记得这一点。 :)
  • 所以我猜你总是会免费获得分配,因为默认实现是一个成员副本,任何类最终都是 POD 的组合,而 POD 显然具有内置分配。因此对象之间的副本将递归地按成员复制,直到到达 POD 副本。那么这只是一个设计决定,无法实现平等吗?好像本来可以的。
  • @StoneThrow 语言设计者(与编译器开发者一起)讨厌复杂性,他们尽可能避免复杂性。在某些 OO 语言的某些实现中,引入默认的比较运算符在技术上可能是可行的……但这是一个现实。如何默认比较一个没有任何字段的类的两个对象?如何默认比较单个基类的不同派生类的两个对象 - 通过它们的基本引用?是否应该比较 mutable 字段?等等。这将带来一大堆复杂性,而 C++ 本身就充满了。
猜你喜欢
  • 1970-01-01
  • 2015-12-14
  • 2014-10-21
  • 2012-10-10
  • 2012-11-02
  • 2015-04-09
  • 1970-01-01
  • 2013-04-11
  • 2011-11-16
相关资源
最近更新 更多