初始化列表:复制构造函数和赋值运算符 = 冗余?
Posted
技术标签:
【中文标题】初始化列表:复制构造函数和赋值运算符 = 冗余?【英文标题】:Initializer lists: copy constructors and assignment operators = redundancy? 【发布时间】:2011-12-24 20:18:18 【问题描述】:对于您的类构造函数,初始化列表似乎是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)
或者operator=中缺少一行。由于赋值运算符和复制构造函数通常具有相同的效果(因为我们将成员从一个 Foo 复制到另一个)我可以“重用”来自复制构造函数或赋值运算符的代码,反之亦然?
【问题讨论】:
获得正确的复制构造函数和赋值运算符比看起来要困难得多;你真的应该阅读FAQ on the copy-and-swap idiom。另一方面,正如其他人所说,在这种情况下,不需要用户声明的复制构造函数和赋值运算符。 我通常在构造函数中使用operator=:Foo(const Foo & X) *this = X; @freerider:一般来说,如果你的班级管理operator=
在复制之前需要释放的资源,这不是一个好主意。
@matteo italia:我知道,但我刚刚回答了这个示例中不包含堆分配的问题。当然你不应该在更复杂的类中使用。
【参考方案1】:
将所有内容转发给赋值运算符可能无效,但这在允许的 C++03 中很常见。
在 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);
但请记住,这个不能在一些常见的情况下使用。 (任何不可分配的对象)
【讨论】:
【参考方案2】:您的目标应该是根本不编写复制构造函数/赋值运算符。你的目标应该是让编译器来做。标准库容器都是可复制的,因此请在合理的情况下使用它们。
如果存在无法正确复制的成员,则使用智能指针或其他 RAII 对象。这些对象应该需要特殊的复制构造函数/赋值。他们只需要他们一个成员。
其他一切都不应使用它们。
【讨论】:
构造函数很常见,可以做出很多选择。不过我同意分配。 @MooingDuck:但是 copy 构造函数可以留给编译器编写(至少如果让编译器编写复制赋值运算符是安全的,它应该是安全的) .... = default;
是你的朋友;使用它。
@MooingDuck 编译器,甚至是 VC2010,都会尽可能为你创建一个拷贝构造函数和拷贝赋值运算符。唯一不会的情况是您的成员没有复制构造函数/赋值。
@MooingDuck:为什么?只需要让编译器生成一个做正确的事,即使你定义了其他构造函数,你也不必定义它。【参考方案3】:
由于赋值运算符和复制构造函数通常具有相同的效果。
一点也不,一个做初始化,另一个做赋值。它们在对象的初始状态上是不同的,它们的任务是分开的(尽管相似)。规范赋值运算符通常是这样完成的:
Foo& operator=(Foo right)
right.swap( *this );
return *this;
【讨论】:
以上是关于初始化列表:复制构造函数和赋值运算符 = 冗余?的主要内容,如果未能解决你的问题,请参考以下文章
依赖项没有复制 ctor 或赋值运算符时的 C++ 初始化程序列表