对于你的类构造函数来说,initalizer列表似乎是good idea,我也假设,对于复制构造函数也是如此。对于赋值运算符,必须在函数体中分配每个成员。考虑以下简单的块:
class Foo {
private:
int a,b;
public:
Foo(int c, int d) : a(c), b(d) {}
Foo(const Foo & X) : a(X.a), b(X.b) {}
Foo& operator=(const Foo& X) {
if (this == &X) return *this;
a = X.a;
b = X.b;
return *this;
}
};
如果一个类有适量的数据成员,那么有三个地方可以搞乱不同的分配/初始化。我的意思是,如果复制构造函数看起来像:
Foo(const Foo & X) : a(X.a), b(X.a) {}
或者运营商缺少一条线=。由于赋值运算符和复制构造函数通常具有相同的效果(因为我们将成员从一个Foo复制到另一个Foo),我可以“重用”复制构造函数或赋值运算符中的代码,反之亦然吗?
答案 0 :(得分:10)
您的目标应该是不要编写复制构造函数/赋值运算符。你的目标应该是让编译器去做。标准库容器都是可复制的,因此在合理的情况下使用它们。
如果有成员无法正确复制,则使用智能指针或其他RAII对象。那些对象是需要特殊拷贝构造函数/赋值的对象。他们只需要他们的一个成员。
其他一切都不应该使用它们。
答案 1 :(得分:3)
由于赋值运算符和复制构造函数通常具有相同的效果。
完全没有,一个进行初始化而另一个进行分配。它们在对象的初始状态不同,它们的任务是分开的(虽然相似)。规范赋值运算符通常用:
Foo& operator=(Foo right) {
right.swap( *this );
return *this;
}
答案 2 :(得分:2)
将all转发给赋值运算符可能无效,但这是允许在C ++ 03中的commmon。
在C ++ 11中,构造函数更容易:将所有构造函数转发给一个主构造函数。
class Foo {
private:
int a,b;
public:
Foo(int c, int d) : a(c), b(d) {}
Foo(const Foo & X) : Foo(x.a, x.d) {}
//syntax may be wrong, I don't have a C++11 compiler
Foo& operator=(const Foo& X) {
if (this == &X) return *this;
a = X.a;
b = X.b;
return *this;
}
}
在C ++ 03中(允许)
class Foo {
private:
int a,b;
void init(int c, int d) {a=c; b=d;}
public:
Foo(int c, int d) : {init(c,d);}
Foo(const Foo & X) : {init(X.a, X.b);}
Foo& operator=(const Foo& X) { init(X.a, X.b);}
}
但请记住,不能在某些常见情况下使用。 (任何不可分配的对象)