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

默认(空)构造函数 复制构造函数 一个析构函数 赋值运算符(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结构体的兼容性。然而,它们确实会造成足够多的破坏,让开发人员忘记它们或默认实现的语义。

其他回答

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.

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

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

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

在这个视频中,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++ 20开始,它可以通过命令auto操作符自动生成<=>(const foo&) const = default;

它将生成所有的运算符:==,!=,<,<=,>和>=,详细信息请参见https://en.cppreference.com/w/cpp/language/default_comparisons。

由于操作员的外观<=>,它被称为宇宙飞船操作员。另见为什么在c++中我们需要太空船<=>操作符?

EDIT:同样在c++ 11中,std::tie也提供了一个相当简洁的替代品,有关bool操作符<(…)的完整代码示例,请参阅https://en.cppreference.com/w/cpp/utility/tuple/tie。有趣的部分,改变为使用==是:

#include <tuple>

struct S {
………
bool operator==(const S& rhs) const
    {
        // compares n to rhs.n,
        // then s to rhs.s,
        // then d to rhs.d
        return std::tie(n, s, d) == std::tie(rhs.n, rhs.s, rhs.d);
    }
};

tie适用于所有比较操作符,并被编译器完全优化。