为什么不允许复制构造函数和赋值运算符?

Why copy constructor and assignment operator are disallowed?

提问人:MainID 提问时间:8/6/2010 最后编辑:MainID 更新时间:8/6/2010 访问量:5275

问:

#undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS
#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName)    \
   TypeName(const TypeName&);                           \
   void operator=(const TypeName&)

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

C++

评论

1赞 Sjoerd 8/6/2010
它们被称为“复制构造函数”和“赋值运算符”。没有赋值构造函数这样的东西。
2赞 Johannes Schaub - litb 8/6/2010
我会称它们为“构造函数”和“赋值运算符”或“复制构造函数”和“复制赋值运算符”
2赞 Martin York 8/7/2010
我不会称他们为邪恶,那样会给他们带来不好的色彩。只需像 boost 一样禁用它们:boost::noncopyable

答:

12赞 anon 8/6/2010 #1

防止复制或分配类的实例。大多数类不应允许复制。以BankAccount类为例,如果你正在为一家银行编写软件,如果你创建账户的副本,然后将贷方和借方应用于这些不同的副本,他们不会太高兴。

评论

0赞 KedarX 8/6/2010
+1 .... @DumbCoder 如果您是该银行软件的编码员,那将是可能的!
0赞 MainID 8/10/2010
@Neil Butterworth:为什么不直接使用单例呢?
4赞 8/10/2010
@MainId 一个单一的账户意味着只能存在一个银行账户——银行必须拥有数千个东西。
0赞 E. Vakili 6/20/2020
说大多数类应该禁止复制是不正确的。顺便说一句,谷歌是这么认为的。
1赞 Anthony Williams 8/6/2010 #2

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

8赞 jamesdlin 8/6/2010 #3

复制构造函数和复制赋值运算符的问题在于,如果未显式声明实现,编译器会自动生成实现。

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

违反三巨头定律通常会导致错误,例如数据成员的双重释放和内存损坏。出现这类错误的情况并不少见,因为该类的作者从不费心去考虑复制行为,而且因为消费者很容易无意中复制对象。

除非类的作者实际上已经考虑过如何正确复制该类的实例(或者除非该类有一个微不足道的析构函数),否则最好明确禁止复制以避免潜在的问题。然后,可以推迟实现可复制性,直到有实际需要为止。

评论

4赞 David 8/6/2010
这正在成为“五大法则”,即将推出的标准C++0,并添加了移动构造函数/赋值!
1赞 jamesdlin 8/7/2010
@David:move 构造函数/move-assignment 运算符将选择加入(如果您省略它们,编译器将不会为您生成它们)。
0赞 David 8/7/2010
你是对的,但如果你关心性能,你也会提供它们。