关于C++的拷贝构造函数,很多的建议是直接禁用。为什么大家会这么建议呢?没有拷贝构
造函数会有什么限制呢?如何禁用拷贝构造呢?这篇文章对这些问题做一个简单的总结。
这里讨论的问题以拷贝构造函数为例子,但是通常赋值操作符是通过拷贝构造函数来实现
的( copy-and-swap 技术,详见《Exceptional C++》一书),所以这里讨论也适用于赋
值操作符,通常来说禁用拷贝构造函数的同时也会禁用赋值操作符。
^1
,也就是逐个拷贝成员变量,对于
下面这个类的定义
^2
:
1 2 3 4 5 6 7 8 9
|
class Widget { public: Widget(const std::string &name) : name_(name), buf_(new char[10]) {} ~Widget() { delete buf_; }
private: std::string name_; char *buf_; };
|
默认生成的拷贝构造函数,会直接拷贝
buf_
的值,导致两个
Widget
对象指向同一个缓
冲区,这会导致析构的时候两次删除同一片区域的问题(这个问题又叫
双杀
问题)。
解决这个问题的方式有很多:
自己编写拷贝构造函数,然后在拷贝构造函数中创建新的
buf_
,不过拷贝构造函数的
编写需要考虑异常安全的问题,所以编写起来有一定的难度。
使用
shared_ptr
这样的智能指针,让所有的
Widget
对象共享一片
buf_
,并
让
shared_ptr
的引用计数机制帮你智能的处理删除问题。
禁用拷贝构造函数和赋值操作符。如果你根本没有打算让
Widget
支持拷贝,你完全可
以直接禁用这两操作,这样一来,前面提到的这些问题就都不是问题了。