析构函数&&构造函数:
1.析构函数:当一个生命周期结束时,C++系统会默认调用的一个成员函数。
——将对象定义在其中,保证在结束时对象被清理。
2.构造函数:在创建变量时,C++系统默认调用的一个成员函数。
——保证对象一定被初始化
*※既然系统会默认调用构造函数,那么为什么还要自己写呢?
——拷贝时,如果是简单的拷贝值,即浅拷贝时,可以不写。但如果是深度拷贝,则需要自己写构造函数。
Date(Date&s);
//使用Date时,无需写构造函数,直接调用即可。
//使用String时,若是简单的浅拷贝,则会存在问题。(拷贝构造)
//将s2拷贝给s3
String s2("change world)";
String s3(s2);
浅拷贝:
浅拷贝存在的问题:
1.两个指针指向一块空间,如果对s2指向空间的数据进行改变时,s3的指向也会发生改变。
2.当编译结束时,会产生两次析构。(s2和s3都会对动态开辟的空间进行释放,则将同一块空间释放两次。)
深拷贝:
//将s2改动对s3毫无影响,将s2开辟的空间进行析构,对s3也无影响。
//s3(s2)
String(const String&s)
:_str(new char[strlen(s._str) + 1])//s._str相当于s2,构造s2
{
strcpy(_str, s._str);//将s2拷贝给s3,_str相当于s3
}
拷贝构造&&赋值运算符的重载 ;
赋值运算符的重载:
//s1=s2
String & operator=(const String&s)
{
if(this == &s)//自己拷贝自己
{
return *this;
}
char* tmp=new char[strlen(s._str) + 1];
if(tmp != NULL)
{
delete[] _str;
_str=tmp;
strcpy(_str,s._str);
}
return *this;
}
※既然系统会默认调用析构函数,那么为什么还要自己写呢?
Class Date()
{
public:
Date(int year=1900)
:—year(year=2018)
{}
private:
int _year;
}
//系统调用的析构函数构造如下:
~Date()
{}
//这种只需传值的就可以由系统自行调用
使用String时,就需要自行写析构函数
class String
{
public:
String(char*_str="",size_t size=0)
:_str(str),_size(size);
{}
private:
char*_str;
size_t size;
}
如上图所示,_str是一个指针,这个指针指向一个空间,而系统直接调用的析构函数构造如下:
~String()
{}
系统调用的析构函数只能释放_str,而不能释放 _str所开辟的空间。
//正确的析构方式
~String()
delete[]_str;
{}