拷贝构造函数、析构函数
一、拷贝构造函数
(一)、何为拷贝?
拷贝一词来源于英文中的copy,译为:抄写,复制,复制品。将原有物件,按照同样式的在来一份。
**举个栗子:
饭点到了,和朋友一起去吃饭。
我兴高采烈地跟老板说:“老板,来碗饺子”。
(别问我为什么是饺子,如果一定想知道,好吧,我承认我对饺子爱的深沉)
这个时候,老板说“要得,稍等!”。
又转问我朋友吃啥。
不料他也说:“饺子一碗”!
“你这人,不是拷贝我嘛!!!”
好了,说到这儿,你大概知道拷贝是什么意思了,那么,我们就趁热打铁。
(二)、拷贝构造函数
前面我们介绍了构造函数,详情见
http://blog.csdn.net/dai_wen/article/details/78328965,那么, 这里的拷贝构造函数是不是跟它有血缘关系呢?下面,就来探个究竟。
1.定义:
首先, 拷贝构造函数是函数,它是特殊的构造函数。仅有一个形参,该形参是本类类型对象的引用,创建对象时,使用已存在的同类对象对自身进行初始化,又编译器自动调用。
A:
CDate (const CDate& date,const CDate& time)
{
}
//在该函数中有两个形参,故而断定它不是拷贝构造函数
B:
CDate (const CDate date)
{
}
//在该函数中,形参部分不是类类型的引用,故而断定它不是拷贝构造函数
2.举个栗子:
class Date
{
public:
//构造函数
Date(const int year ,const int month,const int day )
{
_iyear=year;
_imonth=month;
_iday=day;
}
//拷贝构造函数
Date(const Date& date)
{
_iyear=date._iyear;
_imonth=date._imonth;
_iday=date._iday;
}
private:
int _iyeay;
int _imonth;
int _iday;
};
void FunTest(Date& date)
{
return date;
}
int main()
{
Date d1(2017,10,23);
FunTest(d1);
Date d2(1995,08,15);
d2=FunTest(d1);
return 0;
}
在该程序中, 显然,d2是d1的一份拷贝。
3. 由此看透:
(i)拷贝构造函数是构造函数的重载
(ii)形参类型必须是相同类的构造函数的引用
(iii)若没有显式定义,系统会自动合成默认的拷贝构造函数,它会依次拷贝类的数据成员完成初始化。
4.使用场景:
(1)、对象实力化对象。
Date d1(2017,10,23);
Date d2(d1);
(2)、传值方式作为函数的参数
void FunTest(const CDate date)
(3)、传值方式作为函数的返回值
CDate FunTest()
{
CDate date;
return date;
}
5. 打倒面试题:
思考题1:为什么形参必须引用?不传引用可以吗?
解析:答案是肯定不可以的 。
Date d1(2017,10,29);
Date d2(d1);
如果不传引用,仅采用传值的方式,那么,当程序运行到Date d2(d1)时,将无限重复执行该语句,形成无限递归,程序无法正常实现功能。
二、析构函数:
(一)、定义:
析构函数与构造函数的功能恰好相反。在对象被销毁时,由编译器自动调用,完成类的一些“清理”和汕尾工作。
(二)、形式:~函数名()
(三)举个栗子:
class CArray
{
public:
CArray(size_t capacity)
:_capacity(capacity)
{
_PData=(int *)malloc(capacity* sizeof(int));
_size=0;
}
~CArray()//析构函数
{
if(NULL!=_PData);
{
free(_PData);//
_PData=NULL;//清理、释放内存
}
_size=0;
_capacity=0;
}
private:
int * _PData;
size_t_size;
size_t_capacity;
};
(四)、析构函数特性:
1、析构函数在函数名前加一个~;
2、没有任何参数
3、没有返回值
4、一个类中只有一个构造函数
5、在对象生命周期结束时,C++ 编译器自动调用析构函数
6、析构函数本质上并不是删除对象,而是做一些清理工作。
三、有奖竞答:
留个栗子给大家剥:
思考题:既然编译器会自动合成拷贝构造函数,那么,它还有没有给出的必要? 什么情况下必须给出?
还没有评论,来说两句吧...