默认构造函数,复制构造函数和析构函数非常重要,我理解为什么C ++隐式定义它们。只考虑应该复制的函数参数,应该被破坏的局部变量以及即使你没有说明如何构造也应该构造的对象。
但为什么我们需要复制赋值运算符隐式定义?是否真的必须能够a = b
?这不是游戏改变,对吗?我不知道有什么强烈的理由吗?
答案 0 :(得分:7)
...为什么我们需要复制赋值运算符?
简单地说,支持赋值语义。这些与复制构造语义不同。
Foo f1;
Foo f2(f1); // copy...
Foo f3;
f3 = f1; // assignment...
它们是相似的,通常是相互实现的,但不一样。
为什么要隐式定义它们?
支持和模仿C风格的语义。 这样用户定义的类型可以支持与内置类型相同的语义。
旁注; IIRC,some deprecation of rules here已经出现了移动语义......
答案 1 :(得分:4)
我相信它来自C ++的一个属性/功能,它能够编译本机C代码。
在C中,您可以将一个struct
变量分配给另一个,例如
typedef struct foo_s
{
int field1;
int field2;
} foo_t;
int main ()
{
foo_t a, b;
a.field1 = 1;
a.field2 = 2;
b = a;
return 0;
}
因此,您应该能够将此代码编译为C ++,因此必须具有默认赋值运算符。
答案 2 :(得分:1)
如果复制构造对象,则可以设置const成员。想象一下,你已经有了一个对象,然后想做一个任务。这会违反成员的常数。
为了澄清这一点 - 因为这个简短的文字似乎不适合大多数人 - 这里有一些代码:
struct C {
const int i;
C(int i) :i(i) {};
};
int main(void) {
C a(5), b(7);
a = b; // compiler error
C c(a); // no error
return 0;
}
所以你需要赋值运算符,因为它有不同的语义。
隐式定义 - 如果可能 - 因为应尽可能默认定义赋值。请注意,在大多数情况下,您的赋值运算符实际上是不是隐式定义的。上面的代码只是一个例子,但还有很多其他情况:例如,如果你有一个用户声明移动构造函数,那么复制赋值运算符是不是隐式定义的。