类与对象——6大默认成员函数(一)

0 什么是默认成员函数

之前我们知道类的内部可以没有任何成员,我们称为空类。那空类内部真的什么都没有吗?其实不然,类内部什么都不写时编译器会默认生成6大默认成员函数在这里插入图片描述

我们主要学习的是前四个函数:构造函数,析构函数,拷贝构造函数,赋值重载函数。最后两个一般不用我们自己书写,因此做简单介绍即可。

1. 构造函数与析构函数(重点,易混淆点)

1.1 构造函数

构造函数是特殊的成员函数,构造函数的主要任务是初始化对象,记住构造函数不是创建对象!!!!!

构造函数的定义

1.构造函数的函数名与类名相同;
2.构造函数无返回值也不需要写返回值(不需写void);
3.构造函数支持重载。
在这里插入图片描述
4.对象实例化时编译器会自动调用对应的构造函数;在这里插入图片描述

构造函数的特性

1.如果我们不自己写那编译器会自动生成一个构造函数,一旦我们自己写了任意一个构造函数编译器将不再自己生成。
那既然编译器会自己生成那为什么还要我们自己写呢?我们不妨来看下面的实验:在这里插入图片描述
同学们估计又有疑问了,尽然他什么都不做,那没任何意义,为啥还要自动生成啊?每次自己写不就好了吗?未解决这个疑问,我们不妨来看看下个性质:
2.系统默认的构造函数对数据的处理分两种情况:
(1)内置类型(int,double,char……):编译器不作任何处理!!!
(2)自定义类型(struct,class):调用其默认构造函数(这又是什么呢?)。
在这里插入图片描述
在这里插入图片描述

默认构造函数(1)指无参的构造函数,(2)全缺省的构造函数,(3)编译器默认生成的构造函数,默认函数只能有一个。在这里插入图片描述
介于上述对内置类型系统自动重生成的默认构造函数不处理这件事的不合理性,在C++11标准中,又给出下列语法:
内置类型成员变量在声明处给默认值进行初始化。在这里插入图片描述
C++有关构造函数的语法设计较为复杂,我们是否需要自己写构造函数具体还得看成员的数据类型及初始化的需求情况来定,但一般情况都需要自己写构造函数,因为自定义类型都由内置类型组成,最后的构造函数都需要我们自己写

1.2 析构函数

析构函数的功能与构造函数的功能完全相反,在对象销毁时调用析构函数,完成对象中资源的清理工作,记住析构函数不是销毁对象!!!!!对象的销毁由编译器自己完成。

析构函数的定义

1.析构函数名在类名前面加上“~”;
2.无参数无返回值类型;
3.一个类只能有一个析构函数,析构函数不支持重载!!!!
4.对象的生命周期结束(什么是生命周期??)后,编译器会自动调用析构函数。

在这里插入图片描述

析构函数的特性

1.与构造函数一样,若我们不写析构函数编译器将自己生成一个默认的析构函数;
2.系统默认生成的析构函数(1)对内置类型不作任何处理(这一点很容易理解,因为内置类型不需要资源的清理只需要销毁)(2)对自定义类型调用它的析构函数。

在这里插入图片描述在这里插入图片描述
3.当类中无资源申请时,即不动态开辟空间(malloc,new…)完全可以忽略析构函数不写,直接使用系统默认的析构函数,但当有资源申请时一定要自己写析构函数,不然会导致内存泄露。

析构函数的调用顺序

前面我们提到,当变量的生命周期结束后,会自动调用析构函数,不同的变量生命周期不同
析构函数的调用满足下面的特点:
1.局部变量——局部静态——全局变量(无论是不是静态变量都一视同仁)
2.后定义的先析构;

在这里插入图片描述

2. 拷贝构造函数与赋值重载函数(重点难点)

2.1 拷贝构造函数

拷贝构造实质上是构造函数的一个重载,在实际应用中我们也许经常会遇到用一个已存在的对象去创建一个新的对象的场景,这时就轮到拷贝构造出场了。

拷贝构造函数的特性

1.拷贝构造是构造函数的一个重载;
因为拷贝构造也是构造函数,若往后我们不写默认构造函数编译器就会报错,因为有了拷贝构造编译器就不会自动生成默认的构造函数了,有了拷贝构造,往后我们必须写一份默认构造函数。在这里插入图片描述

2.拷贝构造的参数只有一个且必须是类对象的引用
(为什么一定要是引用呢?)
至于为什么一定要是引用不能是传值是因为C++标准中给出了这样一个规定:
C++中传值传参一定要调用拷贝构造函数!!!!!!
下面我们在来做一个实验,我们写一个含有显示拷贝构造的类,用两个任意函数调用类对象看看会发生什么?(我们已经知道在C语言中传值调用是要临时拷贝的!!!!)在这里插入图片描述
上边这个代码会发生什么呢?我们不妨来调试一下(test1传值,test2传引用)在这里插入图片描述这里十分有力的证明了:传值传参会调用拷贝构造函数,而传引用不会调用拷贝构造
有了这样一个认识我们就能够清晰的解释为什么不能拷贝构造的形参不能为传值?在这里插入图片描述
没错如果使用传值会陷入无穷无尽的递归调用!!!!,使用引用能完美解决所有问题。
3.若我们不自己写拷贝构造函数,编译器也会自动生成一个默认拷贝构造函数,这个拷贝构造函数:(1)它会对内置类型进行浅拷贝(2)对自定义类型成员则调用它的拷贝构造
那有同学可能就会说内置类型都能处理了那拷贝构造是不是不用我们自己写了,其实不是的,编译器仅仅会做浅拷贝而浅拷贝对于一些对象是远远不够用的。
那什么是浅拷贝呢?
这里有涉及两个拷贝的概念:浅拷贝与深拷贝

浅拷贝与深拷贝

浅拷贝

当拷贝的对象有指针时:编译器自动生成的拷贝构造函数就会出问题,我们以数据结构栈为例:在这里插入图片描述
我们发现以上代码运行之后,编译器报错了!!!在这里插入图片描述
其实原因如下:在这里插入图片描述
其实上诉的拷贝过程就叫做浅拷贝

深拷贝

深拷贝其实主要针对有指针的情况:另外开辟空间进行拷贝将原指针指向的内容全部拷贝到新的空间在这里插入图片描述
在这里插入图片描述

了解了浅拷贝与深拷贝,我们是否需要些拷贝构造就取决于我们是否需要申请资源,有资源申请那一定要写拷贝构造,否则浅拷贝不需要写。

赋值重载(十分重要!!!!)

由于赋值重载牵扯函数重载的内容,这一块分特别重要且内容多且杂,将此内容分出一章来单独讲解!见下章节

  • 30
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值