2010-08-06 95 views
7
#undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS 
#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName) \ 
    TypeName(const TypeName&);       \ 
    void operator=(const TypeName&) 

我是,从谷歌阅读开源代码。 为什么复制构造函数和赋值运算符是不允许的?为什么复制构造函数和赋值运算符是不允许的?

+1

它们被称为“复制构造函数”和“赋值运算符”。作为赋值构造函数没有这样的事情。 – Sjoerd 2010-08-06 08:40:05

+2

我会称它们为“构造函数”和“赋值运算符”或“复制构造函数”和“复制赋值运算符” – 2010-08-06 09:16:18

+2

我不会调用EVIL,这种颜色让它们在恶劣的光线下着色。只需禁用它们就像boost:boost :: noncopyable – 2010-08-06 18:19:33

回答

12

防止正在复制或分配的类的实例。大多数类不应该允许复制。考虑一个例如BankAccount类 - 如果您正在为银行编写软件,如果您创建帐户副本,然后将信用和借记应用于这些不同副本,他们就不会太高兴。

+0

完美的例子。我多么希望他们允许它:) !!!! – DumbCoder 2010-08-06 08:39:59

+0

+1 .... @DumbCoder如果你是该银行软件的编码器,它将成为可能! – KedarX 2010-08-06 10:30:58

+0

@Neil Butterworth:为什么不直接用单身呢? – MainID 2010-08-10 03:13:25

1

如果您的类型包含指针或引用成员,或者它没有语义上的意义(例如它有一个必须在析构函数中释放的资源句柄),那么禁用复制构造函数和赋值运算符。在C++ 0x中(例如,在g ++ 4.4或更高版本中,在-std = C++ 0x模式下),您可以声明它们已被删除。在较早的编译器中,您只需将它们声明为私有并且未实现。

7

复制构造函数和复制赋值操作符的问题是,如果编译器没有明确声明,编译器会自动生成实现。

这很容易导致意想不到的问题。如果一个类具有非平凡的析构函数,那么它几乎总是需要为复制构造函数和复制赋值运算符提供它自己的实现(这是Law of the Big Three),因为默认的编译器生成的通常会做错误的事情。

违反三大法则往往会导致数据成员和内存损坏等错误。出现这种类型的错误并不罕见,因为类的作者从来不会考虑复制行为,而且消费者很容易无意中复制对象。除非类的作者已经真正考虑过如何正确地复制该类的实例(或者除非该类具有微不足道的析构函数),否则最好明确禁止复制以避免潜在的问题。实现可复制性可以推迟到实际需要时为止。

+4

随着即将推出的标准C++ 0x与移动构造器/作业的增加,这正成为“五大法则”! – David 2010-08-06 13:16:44

+1

@David:移动构造函数/移动赋值运算符将被选入(如果忽略它们,编译器将不会生成它们)。 – jamesdlin 2010-08-06 17:38:09

+0

你是对的,但如果你关心表现,你也会提供。 – David 2010-08-06 17:48:25