如果有一个例如以下的MyClass类:
class MyClass { public: //构造函数 //拷贝构造函数 MyClass(const MyClass& that) : int_data_(that.int_data_), dbl_data_(that.dbl_data_), str_data_(that.str_data_) { } //赋值操作符 MyClass& operator = (const MyClass& that) { if(this != that) { int_data_ = that.int_data_; dbl_data_ = that.dbl_data_; str_data_ = that.str_data_; } return *this; } //一些其它方法 private: Int int_data_; Double dbl_data_; string str_data_; //每次在这里加入一个新的数据成员时,不要忘了在拷贝构造函数和赋值操作中加入相应的代码 };
对于这个类,存在什么问题呢?真正的问题是,在私有部分后面的凝视指出了问题的所在。假设像凝视中所说的,这种操作特别麻烦并且极易犯错误。其实,假设我们没有编写拷贝构造函数和赋值操作符,C++会为我们编写一个“默认版本号”。
拷贝构造函数的默认版本号为全部的数据成员调用拷贝构造函数(或简单的复制内置类型),赋值操作符的默认版本号将调用每一个数据成员的赋值操作符或者简单的复制内置类型。
因此,对于上面的样例,拷贝构造函数和赋值操作符全然没必要的。更糟的是,它们是潜在的错误之源,由于它们使代码变得脆弱。假设有人试图改变它们,就可能对代码产生破坏。
因此,对于上述的样例,比較好的思路是彻底避免编写拷贝构造函数和赋值操作符。
一般而言,有几种方式可供选择:
- 依赖编译器自己主动创建的默认版本号
- 把拷贝构造函数和赋值操作符声明为私有,而且不提供实现,禁止不论什么类型的复制
- 编写自己的版本号
总结:
- 仅仅要有可能,避免编写拷贝构造函数和赋值操作符
- 假设默认版本号并不适用,能够考虑把拷贝构造函数和赋值操作符声明为私有,禁止类实例的复制