c++中有中说法叫做复制控制,包含以下三种:
1 复制构造函数
2 赋值操作赴
3 析构函数
详细部分大家可以参见:c++ primer 第四版第13章。在这里我想强调两点:
1.复制构造函数和赋值操作符的区别:复制构造函数是在对象初始化时进行的,与之相对应的是直接初始化(用构造函数实现),而赋值操作符的顺序是先要删除原对象的内容,然后将右操作数赋值给左操作数。
2.析构时的析构顺序
我们先来看第一个例子吧:
#include<iostream>
using namespace std;
class Sales{
public:
Sales(int a=0,int b=0):i(a),j(b)
{
cout<<"call sales constructor"<<endl;
}
Sales(const Sales& org):i(org.i),j(org.j)
{
cout<<"call sales copy constructor"<<endl;
}
Sales& operator=(const Sales &rhs)
{
cout<<"call sales operator ="<<endl;
i=rhs.i;
j=rhs.j;
return *this;
}
~Sales()
{
//cout<<"call delete function"<<endl;
}
private:
int i;
int j;
};
int main()
{
Sales s1(1,2);
Sales s2(s1); //调用复制构造函数
Sales s3=s1; //调用复制构造函数,注意与下面的进行比较 输出call sales copy constructor
s2=s1; //这是赋值操作符,大家看到区别了吧 输出call sales copy operator
return 0;
}
结果如下
接下来我们通过第二个例子来说明
#include<iostream>
#include<string>
using namespace std;
class Sales{
public:
Sales(const string &str=" "):s(str)
{
cout<<"call sales constructor"<<endl;
}
Sales(const Sales& org):s(org.s)
{
cout<<"call sales copy constructor"<<endl;
}
Sales& operator=(const Sales &rhs)
{
cout<<"call sales operator ="<<endl;
s=rhs.s;
return *this;
}
void set_str(string str)
{
s=str;
}
~Sales()
{
cout<<s<<":call delete function"<<endl;
}
private:
string s;
};
int main()
{
Sales s1("s1");
Sales s2(s1);
Sales s3=s1;
s2=s1;
s1.set_str("s1");
s2.set_str("s2");
s3.set_str("s3");
return 0;
}
输出结果为:
我们发现,析构的顺序是按照 s1 s2 s3 定义顺序的逆序进行析构的。
而且在析构的时候有一点要注意:即使我们定义了析构函数,系统也还会自己再定义一个析构函数,这是一种设计策略,称为错误导向。即总是按照最坏的情况考虑。