类的默认成员函数


为什么会有构造函数和析构函数呢?
1、初始化和销毁经常忘记
2、有些地方写起来很繁琐.
Stack有了构造和析构,就不怕忘记写初始化和清理函数了,也简化了
例如在队列oj时,忘记释放,造成内存泄漏
在这里插入图片描述

构造函数

主要任务:初始化对象
我们不写,编译器会自己生成
特征:

  1. 函数名和类名相同
  2. 无返回值(也不需要写void)
  3. 对象实例化时编译器自动调用对应的构造函数
  4. 构造函数可以重载

构造函数需特殊对待,在调用上也很特殊(如果构造函数不是默认构造函数
默认构造函数是不需要传参的构造函数(我们没写编译器默认生成的构造函数,全缺省构造函数,无参的构造函数)

那么默认生成的构造函数,处理下面的成员变量仍然是随机值?

在这里插入图片描述
它都做了什么?
我们不写,编译器默认生成构造函数,内置类型不做处理,自定义类型会去调用他的默认构造。 
有些编译器也会处理但是那是个性化行为不是所有编译器都会处理
在这里插入图片描述
C++区分内置类型和自定义类型
1、内置类型/基本类型、语言本身定义的基础类型int/char/double/指针(任意类型的指针)等等
2、自定义、用struct/class等等定义的类型

结论
1、一般情况下,有内置类型成员,就需要自己写构造函数,不能用编译器自己生成的
2、全部都是自定义类型成员,可以考虑让编译器自己生成(编译器会调用自定义类型的构造函数,当然自定义类型的构造函数本身还是需要我们来写的,在这个前提下,只有自定义类型的类就不需要写构造函数)

按理说默认生成的构造函数应该处理一下,不应该是随机值
C++11 给的补丁
在声明成员变量时,给缺省值,给默认构造用,而且这不是初始化,只是声明
在这里插入图片描述

析构函数

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

不写析构,那么类中没有动态申请的资源,对象的成员变量由编译器调用它的析构函数进行释放
即使你写了空的析构,编译器依然会释放成员变量,析构函数只对动态申请的资源进行清理

特性:

  1. 析构函数名是在类名前面加上字符~
  2. 无参数,无返回值类型
  3. 一个类只有一个析构函数,未显示定义,系统自动生成默认的析构函数。并且析构函数不可以重载
  4. 对象声明周期结束,C++编译器自动调用析构函数

默认生成的析构函数做了什么?  
1、内置类型成员不做处理  
2、 自定义类型会去调用他的析构函数

什么时候写,什么时候不写?
1、一般情况下,有动态申请资源,就需要显示写析构函数释放资源
在这里插入图片描述

2、没有动态申请的资源,不需要写析构
在这里插入图片描述

3需要释放资源的成员都是自定义类型,不需要写析构(前提:自定义类型都定义好析构函数)
在这里插入图片描述

析构函数调用顺序问题

函数入栈,后进先出,则后实例化的对象先析构

拷贝构造函数

用一个已经存在的对象初始化另一个对象–拷贝构造
这和 已经存在的两个对象之间复制拷贝 还不一样 (涉及运算符重载函数再解释)
在这里插入图片描述
拷贝构造函数的定义是这么说的
在这里插入图片描述

特征:
拷贝构造函数也是特殊的成员函数,其特征如下:
1.拷贝构造函数是构造函数的一个重载形式
⒉.拷贝构造函数的参数只有一个必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。
3.若未显式定义,编译器会生成默认的拷贝构造函数。默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。

先看看拷贝构造会在什么时候发生

在这里插入图片描述
1.函数参数类型为类类型对象
C++规定了,必须要调用拷贝构造去完成
在这里插入图片描述
2.使用已存在对象创建新对象
在这里插入图片描述

红框也会调用1次拷贝构造
并且红框上面,为什么这里拷贝函数只调用一次,不是应该2次吗,函数传值返回的临时空间拷贝一次,自定义类型赋值一次(虽然是赋值,很像调用了赋值运算符重载函数,但是这是用一个初始化好的对象来初始化另一个未初始化的对象,所以仍然是调用拷贝构造),
答:拷贝构造+拷贝构造 ->优化为拷贝构造

3.函数返回值类型为类类型对象
在这里插入图片描述
下面再来说说无穷递归调用是如何发生的

⒉.拷贝构造函数的参数只有一个必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。

在这里插入图片描述
拷贝构造函数Date(Date d)以传值方式定义形参,在调用 Date d2(d1)初始化d2时,Date d和d1需要拷贝构造,他们是自定义类型,等价于Date d(d1)来初始化d这个形参,Date d(d1)又会有一个新的形参d需要初始化,如此下去,造成死循环

正确写法,要加上const防止修改已经初始化好的对象数据
在这里插入图片描述
拷贝构造为什么形参要加上const ?
在这里插入图片描述

默认生成的拷贝构造函数都干了什么?
1、内置类型成员完成值拷贝/浅拷贝。
2、自定义类型成员会调用他的拷贝构造。

3.若未显式定义,编译器会生成默认的拷贝构造函数。默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。

在这里插入图片描述
日期类直接调用默认的拷贝函数,我们可以不写,就可以完成
但是想stack就需要我们定义拷贝构造函数,而且需要深拷贝,简单的值拷贝,导致st1,st2的值是同一个(数据依次拷贝,top和capacity没事,但a指向的是同一块空间)
造成问题
1.一个数组中的改变会影响另一个
2.析构两次同一块空间,报错
在这里插入图片描述

这个例子可以理解祖师爷为什么规定了需要调用拷贝构造(前提是实现了情况下),而不是像C语言 传值拷贝,导致指向同一块空间

一些调试技巧,利用this看实例化对象
在这里插入图片描述

再来看看为什么要有引用

在这里插入图片描述
上面两种情况,日期类是函数参数类型为类类型对象会调用构造拷贝12字节(类大小)还是传引用都还行,可以接受

在这里插入图片描述
此时函数参数为类类型需要拷贝构造,而且是深拷贝代价比较大,不是简单的值拷贝,就不再想用值传递,而是用引用,提高了效率
在这里插入图片描述

在这里插入图片描述
这种情况也不想传值返回,仍然需要拷贝构造给临时空间返回
减少拷贝的写法
在这里插入图片描述

不能返回被销毁的局部变量的引用
在这里插入图片描述
暂时只能这么写
在这里插入图片描述
虽然效率低一点,但是正确

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值