C++初学——默认成员函数详解(构造、析构、拷贝)

一、构造函数

对于写的一个类来看,定义完成后我们需要对他进行初始化,但是在测试时会有时忘记了写初始化,导致编译错误,所以为了避免这个问题,C++引入了构造函数的概念。

什么时构造函数呢?构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,以保证每个数据成员都有 一个合适的初始值,并且在对象整个生命周期内只调用一次。如图

注意:构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象(想当于Init函数)。

特征:

1、函数名与类名相同。2、没有返回值。3、对象实例化时编译器自动调用对应的构造函数。

4、可以进行函数重载(但是如果是一个全缺省的和一个没有参数的是可以进行重载,但是会对例如下图Date d2会产生调用歧义,所以更加推荐使用带有全缺省的)如下图

 5、 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦

用户显式定义编译器将不再生成。

根据上图可以发现,d2的数据被初始化成了一些随机值。这是为什么呢?下面就来解释一下这个问题。

1、我们没有写,有没有构造函数呢?有的,这个是编译器自动生成的。

2、在C++中把类型分为了自定义类型内置类型,自定义类型就是class/struct.....,内置类型(基本类型)就是int/char/double/指针等类型。

3、对于编译器自动生成的构造函数而言,内置类型的成员变量是没有规定要进行处理的(有些编译器会进行处理)。而对于自定义类型的成员变量来说就会自动调用他自己的无参构造。

上图里Data没有显示的写构造函数,但是编译器还是进行了初始化,但是成员变量里面既有自定义类型,又有内置类型。内置类型看编译器,但是自定义类型Stack A就会去调用他自己的无参构造。

假如嵌套的自定义类型里面没有显示的写构造函数,会初始化成功吗?会,但是是随机值(看编译器,可能不是随机值)。

所以为了避免些上面描述的发生,我们可以给内置类型的成员变量设定一个缺省值,来防止出现随机值。

最后,无参构造,全缺省构造,编译器自己生成的构造函数都是默认构造函数,而且有一个就不会出现其他两个

二、析构函数 

既然有初始化的,那必定会有销毁类型的函数——析构函数。

析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作

特征:

1、函数名就是类名前面加上一个“~”

2、没有参数而且没有返回值类型。

3、对象生命周期结束时,C++编译系统系统自动调用析构函数。

4、. 一个类只能有一个析构函数。注意:析构函数不能重载

5、若未显式定义,系统会自动生成默认的析构函数。这个与构造函数是类似的。

但是根据上面发现,如果没有显式定义是没有完成资源的清理的。这个又跟构造函数相同,所以规则也到差不差。同样的如果我们没有显示的定义,编译器会自动生成,但是编译器自动生成的对内置类型不做处理,对自定义类型会去调用他自己的析构函数(前提是这个析构也是要显示定义的)。

总结

实践发现:有资源需要显示的清理就会用到析构,如List、Stack等。还有就是对于成员变量都是自定义类型就需要写析构。

三、拷贝构造

拷贝构造顾名思义就是把一个复制成另一个。那么拷贝构造到底上面什么呢?让我们往下看。

拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

特征

1、拷贝构造函数是构造函数的一个重载形式

2、拷贝构造函数的参数只能有一个,而且必须是类类型对象的引用。如上图。

注意:这里是必须用引用,不然会出现无穷递归。如下图,我们用函数的方向来讲解,我们创建了一个func函数,把d1的值给给d。首先func函数调用首先要传参,但是自定义类型传值传参会调用拷贝构造(这个可以当成一个规定)。

所以如果不加引用会不断调用拷贝构造,这样下去会出现无穷递归。

 3、若未显式定义,编译器会生成默认的拷贝构造函数。

但是就像上面两种函数对与自定义类型的话。拷贝构造又是什么样的呢?一样的会去调用对应的拷贝构造函数。

4、编译器默认生成的拷贝构造函数可以完成字节序值拷贝,但是对Stack这样类型的还可以吗?

如上图可以发现,运行崩溃了。这是为什么吗?因为拷贝构造是对与值的拷贝,例如上图s2和s1其实是指向同一个内存空间,在程序运行结束时,会调用析构函数,但是这时s1和s2会被销毁,程序会先释放s1,但是s2还是指向那,这时s2在调用析构函数时,会导致这一块空间被释放了两次。所以程序会造成崩溃。

默认生成的拷贝函数是值拷贝,也可以叫做浅拷贝。所以一旦涉及资源的申请,要深拷贝,就要自己去显示的写拷贝构造函数。

总结一下

1、如果没有资源的管理,就不要去显示的写拷贝构造函数,编译器默认生成的就可以用了。

2、如果都是自定义类型的成员,内置类型的成员没有指向资源,也类似默认生成的拷贝构造就行。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值