假设有一个如下的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++会为我们编写一个“默认版本”。
拷贝构造函数的默认版本为所有的数据成员调用拷贝构造函数(或简单的复制内置类型),赋值操作符的默认版本将调用每个数据成员的赋值操作符或者简单的复制内置类型。
因此,对于上面的例子,拷贝构造函数和赋值操作符完全不是必需的。更糟的是,它们是潜在的错误之源,因为它们使代码变得脆弱。如果有人试图改变它们,就可能对代码产生破坏。
因此,对于上述的例子,比较好的思路是彻底避免编写拷贝构造函数和赋值操作符。
一般而言,有几种方式可供选择:
- 依赖编译器自动创建的默认版本
- 把拷贝构造函数和赋值操作符声明为私有,并且不提供实现,禁止任何类型的复制
- 编写自己的版本
总结:
- 只要有可能,避免编写拷贝构造函数和赋值操作符
- 如果默认版本并不适用,可以考虑把拷贝构造函数和赋值操作符声明为私有,禁止类实例的复制