C++拷贝
第一遍看这部分(P452)确实很难理解,回头对照英文的再看看。
拷贝
HasPtr类
这一小节开篇第一句话就让我头大。“管理类外资源的类必须定义拷贝控制成员”
通过不断翻书追根溯源,我捋了一下如何理解这句话。首先我们来看书中所提供的HasPtr类(我这里省略了std作用域):
class HasPtr{
public:
//动态分配一个新的string
HasPtr(const string &s = string()):
ps(new string(s)), i(0) { }
//拷贝对象p到ps指向的地址
HasPtr(const HasPtr& p):
ps(new string(*p.ps)), i(*p.i) { }
private:
string *ps;
int i;
};HasPtr(const string &s = string()): ps(), i() { }构造函数的默认实参s是一个string类型的引用,为空字符串;冒号后面是数据成员ps和i的初值。
HasPtr(const HasPtr& p): ps(new string(*p.ps)), i(*p.i) { }拷贝构造函数,把p的成员函数ps的地址和i值赋给新的对象
Synthesied copy constructor
如果没有为类定义一个拷贝构造函数,编译器会为我们定义一个synthesied copy constructor。
等价于如下的copy constructor:
class Sales_data{
public:
Sales_data(const Sales_data&);
private:
string bookNo;
int units_sold=0;
double revenue = 0.0;
}
Sales_data::Sales_data(const Sales_data &orig):
bookNo(orig.bookNo), units_sold(orig.units_sold),
revenue(orig.revenue)
{ }可以发现synthesied copy constructor把成员数据的默认值赋给对象orig。
Synthesied destructor
当类未定义自己的析构函数时,编译器会为它定义一个合成析构函数(synthesied destructor)
class Saled_data{
public:
~Sales_data() { }
...
};从代码中可以看到,合成析构函数只销毁其成员,而动态分配的指针则需要使用delete来销毁。
因此需要类来定义一个析构函数。
三五法则
需要析构函数的类也需要定义拷贝构造函数和拷贝赋值运算符
class HasPtr{
public:
HasPtr(const string &s = string()): ps(), i() { }
~HasPtr() { delete ps; }
...
};假如我们为HasPtr类定义了一个析构函数,但是使用的是合成版本的拷贝构造函数,那么看下面这个函数:
HasPtr f(HasPtr hp){
HasPtr res = hp;
return res;
}对象hp接受类HasPtr数据成员的默认值。
将对象hp作为参数传入函数f();将hp的内存地址赋给res;函数声明周期结束时销毁res和hp,这两个对象都会调用HasPtr的析构对象。
