我非常支持让编译器为你做尽可能多的工作。当编写一个简单的类时,编译器可以为你提供以下“免费”:

默认(空)构造函数 复制构造函数 一个析构函数 赋值运算符(operator=)

但是它似乎不能给你任何比较操作符——比如operator==或operator!=。例如:

class foo
{
public:
    std::string str_;
    int n_;
};

foo f1;        // Works
foo f2(f1);    // Works
foo f3;
f3 = f2;       // Works

if (f3 == f2)  // Fails
{ }

if (f3 != f2)  // Fails
{ }

这有什么好的理由吗?为什么执行逐个成员的比较是一个问题?显然,如果类分配内存,那么你要小心,但对于一个简单的类,编译器肯定可以为你做这个?


当前回答

从概念上讲,定义平等并不容易。即使对于POD数据,有人可能会说,即使字段是相同的,但它是不同的对象(在不同的地址),它也不一定相等。这实际上取决于操作符的用法。不幸的是,你的编译器不是通灵的,不能推断。

除此之外,默认函数是搬起石头砸自己的脚的好方法。你描述的默认值基本上是为了保持与POD结构体的兼容性。然而,它们确实会造成足够多的破坏,让开发人员忘记它们或默认实现的语义。

其他回答

如果编译器可以提供默认的复制构造函数,它就应该能够提供类似的默认操作符==(),这在一定程度上是有意义的。我认为决定不为该操作符提供编译器生成的默认构造函数的原因可以从Stroustrup在“c++的设计和发展”(第11.4.1节-复制的控制)中关于默认复制构造函数的描述中猜到:

我个人认为这很不幸 定义的复制操作 默认和我禁止复制 我的许多类的对象。 然而,c++继承了它的默认值 赋值和复制构造函数 C,它们经常被使用。

因此,问题不应该是“为什么c++没有默认的操作符==()?”,而应该是“为什么c++有默认的赋值和复制构造函数?”,答案是Stroustrup为了向后兼容C而不情愿地包含了这些项(可能是c++的大部分缺点的原因,但也可能是c++流行的主要原因)。

出于我自己的目的,在我的IDE中,我用于新类的代码片段包含私有赋值操作符和复制构造函数的声明,因此当我生成一个新类时,我没有得到默认的赋值和复制操作——如果我想让编译器能够为我生成这些操作,我必须显式地从private:节中删除这些操作的声明。

It's answered C++ didn't do == because C didn't, and here is why C provides only default = but no == at first place. C wanted to keep it simple: C implemented = by memcpy; however, == cannot be implemented by memcmp due to padding. Because padding is not initialized, memcmp says they are different even though they are the same. The same problem exists for empty class: memcmp says they are different because size of empty classes are not zero. It can be seen from above that implementing == is more complicated than implementing = in C. Some code example regarding this. Your correction is appreciated if I'm wrong.

在这个视频中,STL的创造者Alex Stepanov在13:00左右回答了这个问题。总结一下,在见证了c++的发展之后,他认为:

It's unfortunate that == and != are not implicitly declared (and Bjarne agrees with him). A correct language should have those things ready for you (he goes further on to suggest you should not be able to define a != that breaks the semantics of ==) The reason this is the case has its roots (as many of C++ problems) in C. There, the assignment operator is implicitly defined with bit by bit assignment but that wouldn't work for ==. A more detailed explanation can be found in this article from Bjarne Stroustrup. In the follow up question Why then wasn't a member by member comparison used he says an amazing thing : C was kind of a homegrown language and the guy implementing these stuff for Ritchie told him he found this to be hard to implement!

然后他说,在(遥远的)未来,==和!=将隐式生成。

c++ 0x有一个默认函数的提议,所以你可以说default operator==; 我们已经了解到,把这些事情弄清楚是有帮助的。

恕我直言,没有什么“好的”理由。有这么多人同意这个设计决策的原因是因为他们没有学会掌握基于值的语义的力量。人们需要编写大量的自定义复制构造函数、比较操作符和析构函数,因为它们在实现中使用原始指针。

在使用适当的智能指针(如std::shared_ptr)时,默认的复制构造函数通常是可以的,假设的默认比较运算符的明显实现也可以。