对象的初始化和清理(构造和析构)

news2024/11/26 20:25:06

目录

一. 前言

二. 构造函数和析构函数的语法

三. 构造函数的分类和调用

 四. 构造函数的调用规则

五. 深拷贝和浅拷贝(面试常考)

六. 初始化列表


一. 前言

        任何事物都需要有一个初始化的过程,例如手机,我们在买来使用的时候手机其实就已经被初始化了,如设置的语言为中文等等。同样,在使用后,我们为了自身数据的安全性,就会考虑清楚数据。我们的对象同样如此,也需要一系列的初始化和清理操作。

        为了解决上面这两个问题,我们C++中就可以使用构造函数和析构函数来解决。如果我们 不提供构造函数和析构函数,那么编译器就会自动提供,只是都是空实现,也就是空的代码。

二. 构造函数和析构函数的语法

        构造函数的主要作用就在于创建对象时,为对象的成员属性赋值,会由编译器自动调用。

析构函数的主要作用就在于执行对象销毁前的一些清理工作,也是在销毁前系统自动调用。

        构造函数的语法如下:

类名 (){ }

        构造函数的特点如下:

构造函数没有返回值,也不需要写void。

函数名称和类名相同。

构造函数可以有参数,因此可以发生重载。

程序在调用对象时候会自动调用构造,无须手动调用,而且只会调用一次。

        析构函数的语法如下:

~类名(){ }

        析构函数的特点如下:

函数名称和类名相同,在类名前面加上了一个~符号。

析构函数也没有返回值,也不写void。

析构函数不可以有参数,因此不可以发生重载。

程序在对象销毁前会自动调用析构,无须手动调用,而且只会调用一次。

最后再次声明:构造函数和析构函数都是必须有的实现,如果我们自己不提供,编译器也会提供空实现的构造和析构。

三. 构造函数的分类和调用

        构造函数总共有两个分类方式:

按参数分:有参构造和无参构造

按类型分:普通构造和拷贝构造

如下所示:

class Person{
    Person(){
        cout<<"Person类的无参构造(默认构造)函数"<<endl;
    }
    
    Person(int age){
        cout<<"Person类的有参构造函数"<<endl;
        m_age=age;    //有参构造初始化类属性
    }

    int m_age;
    
    Person(const Person &p){    //拷贝构造里面的形参一般都是这种形式
        cout<<"Person类的拷贝构造函数"<<endl;
        m_age=p.m_age;
    }

    ~Person(){
        cout<<"Person类的析构函数"<<endl;
    }
};

上面这段代码就包括了整个类的构造函数和析构函数的所有类型。

下面我们来看一下在上面这段代码的基础上该如何调用这些函数来完成我们想要实现的功能。

 总共有三种调用方法,分别为:括号法,显示法,隐式转换法

下面我们看第一种调用方式,括号法:

void test01(){
    Person p;    //默认构造函数
    //括号法调用
    Person p1(10);
    Person p2(p1);
}

int mian(){
    test01();
    return 0;
}

运行结果如下所示:

 

分析结果,也就是说test01里面的第一行代码是无参构造,第二行就是有参构造,第三行就是拷贝构造,并且由于这几种构造的调用都是在局部函数当中,运行完就会释放,所以编译器会自动调用析构函数,也就是上述运行结果中的三行析构函数。

下面我们来看下如何使用显示法来调用构造函数:

void test02(){
    Person p1=Person(10);
    Person p2=Person(p1);
}

int mian(){
    test02();
    return 0;
}
    

 运行结果也是和我们所想的一致,如下所示:

这就是显示法调用,其中涉及到了一个比较重要的概念,那就是Person(10)这种形式的,在test02的第一行代码中,是作为右值的,我们只能通过Person(10)来使用Person(10),而没有通过一个变量来使用,就称这样的为一个匿名对象。

匿名对象的特点:当前行执行结束后,系统会立即回收掉匿名对象。因此匿名对象又叫临时对象。

值得注意的是,也不要利用拷贝构造函数初始化匿名对象。因为编译器会认为Person(p3)等价于Person p3

下面我们来看下隐式转换法来调用构造函数:

void test03(){
    Person p1=10;
    Person p2=p1;
}

int main(){
    test03();
    return 0;
}

以上便是三种调用构造函数的所有内容。

 四. 构造函数的调用规则

在了解构造函数的调用规则前,我们首先知道一个概念那就是:

在默认情况下,C++编译器至少给一个类添加三个函数。

1)默认构造函数(无参,函数体为空)

2)默认析构函数(无参,函数体为空)

3)默认拷贝构造函数,对属性进行值拷贝

构造函数的调用规则如下:

1)如果用户定义了一个有参构造函数,C++就不再提供默认无参构造,但是会提供默认拷贝构造。

2)如果用户定义了一个拷贝构造函数,C++不会再提供其他构造函数。

五. 深拷贝和浅拷贝(面试常考)

        在学习了拷贝构造函数之后,我们继续深入了解一下,如果我们自己并没有构造一个拷贝函数,而是利用编译器自带的拷贝函数,这个就叫做浅拷贝操作。

而深拷贝则就是在堆区重新申请空间,进行拷贝操作。

浅拷贝带来的主要问题就是堆区的内存重复释放。

如下所示:

#include<iostream>
using namespace std;

class Person {
public:
    Person() {
        cout << "Person类的无参构造" << endl;
    }

    Person(int age, int height) {
        m_age = age;
        m_height = new int(height);
        cout << "Person类的有参构造" << endl;
    }

    ~Person() {    //析构函数的作用就体现出来了,清除这段数据
        if (m_height != NULL) {
            delete m_height;
            m_height = NULL;
        }
    }
    int m_age;
    int * m_height;
};

void test01() {
    Person p1(18, 180);
    Person p2(p1);
}

int main() {
    test01();
    return 0;
}

上面这段代码就是使用的编译器自带的拷贝构造函数,因为我们没有自己定义一个拷贝构造函数,这也叫浅拷贝操作,但是当我们运行的时候,就会发生如下的错误提示:

原因就是因为浅拷贝操作,就是把p1的年龄和身高全部复制给了p2,而当这两个构造函数结束时,又会执行析构函数,将这个身高指针所指的内存空间清空,由于p2会清空一次,p1也会清空一次,这就导致了内存空间的重复释放,因此编译器就会给你报错。

而想要解决这个问题也很简单,只需我们自己定义一个拷贝构造函数,并使用深拷贝的操作如下所示,只需在上面原代码的Person类中加上这段代码即可 :

Person(const Person& p) {
        m_age = p.m_age;
        m_height = new int(*p.m_height);
        cout << "Person类的拷贝构造" << endl;
    }

重新给存放身高的指针开辟一个空间,这样p1和p2中的身高就指向了不同内存空间,也就不会出现内存空间重复释放的问题了。 

六. 初始化列表

        初始化列表:跟构造函数作用一致,也是用来初始化属性。

语法:

        构造函数():属性1(值1),属性2(值2)。。。{ }

        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2045151.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

win10 上安装部署WSA, 在win10上运行安卓程序

windows上跑安卓程序&#xff0c; 多年前用过蓝叠bluestacks安卓模拟器 甚至还在上面跑过微信 后来听说在bluestacks上用微信&#xff0c; 可能会被封&#xff0c; 就没有后来了 最近折腾在windows上如何投屏&#xff0c;主要是将ios无线投到win10电脑上&#xff08;安卓win10直…

免费文档翻译导出怎么弄?5个文档翻译器替你解决

在日常的工作与学习中&#xff0c;我们时常会遇到需要查阅或撰写跨语言文档的情况。然而面对这些专业性强、词汇量大的文件&#xff0c;逐字逐句地手动翻译不仅耗时费力&#xff0c;还可能因理解偏差导致信息失真。 幸运的是&#xff0c;如今有不少免费文档翻译软件横空出世&a…

LDR6020双盲插便携显示器方案:重塑连接体验的新标杆

在数字化高速发展的今天&#xff0c;便携显示器已成为商务人士、游戏爱好者及远程教育学习者的得力助手。然而&#xff0c;传统便携显示器在接口兼容性与易用性方面常存在诸多不便&#xff0c;如接口方向区分困难、信号类型不匹配等问题。为了彻底解决这些痛点&#xff0c;LDR6…

基于springboot物流管理系统

TOC springboot208基于springboot物流管理系统 第1章 绪论 1.1 研究背景 互联网时代不仅仅是通过各种各样的电脑进行网络连接的时代&#xff0c;也包含了移动终端连接互联网进行复杂处理的一些事情。传统的互联网时代一般泛指就是PC端&#xff0c;也就是电脑互联网时代&…

记录一次 Redis 优化发送数据(使用管道批量传送)

一 项目背景 此前的项目中&#xff0c;鉴于客户方服务器的安全配置对 MQ 中间件有所限制&#xff0c;我们只得采用 Redis 的 list 作为简易的 MQ 来传送报文数据。然而&#xff0c;近段时间客户关闭了相关端口&#xff0c;导致大量数据积压&#xff0c;需要进行补发。在补发过程…

Unity Obfuscator 使用说明

一、Assembly - Settings 1. 核心Unity程序集&#xff08;Assembly-CSharp&#xff09; Obfuscate Assembly-CSharp: 开启 这是Unity的核心程序集&#xff0c;所有没有存储在程序集定义文件&#xff08;assembly definition file&#xff09;中的代码都会被存储在这里。大多数…

排序算法介绍和sort函数应用(明明的随机数,奖学金)

排序算法介绍sort函数应用——[NOIP2006 普及组] 明明的随机数和[NOIP2007 普及组] 奖学金 1.排序算法介绍和常用排序方法复杂度2.sort函数应用2.1.[NOIP2006 普及组] 明明的随机数题目描述输入格式输出格式输入输出样例输入 #1输出 #1 提示2.1.1.题意解析2.1.2.AC代码 2.2.[NO…

win的netassist TCP测试工具和Linux的nc工具使用

写在前面 有时工作中我们编写一些tcp相关的程序&#xff0c;而netassist就是这样一款辅助我们进行TCP功能测试的工具&#xff0c;你可以从这里下载。 1&#xff1a;netassist使用 我们需要一个server程序&#xff0c;可以参考这篇文章&#xff0c;启动server后&#xff0c;就…

【python】Python如何调用外部命令,subprocess模块的详细解读以及应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

7za解压缩工具

1、unzip无法解压缩大于4G的文件 从Windows平台通过MobaXterm上传一个大小约为5G的zip文件到AutoDL Linux系统上&#xff0c;使用unzip解压过程中出现如下错误&#xff1a; 从网上搜索了一下相关资料&#xff0c;发现是当前的unzip版本不支持4G以上的压缩包。要么升级到最新…

N8 - 使用Word2Vec进行文本分类

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 目录 N2 构建词典1. 导入数据2. 设置分词器3. 去除标点和停用词4. 文本迭代器5. 构建词典6. 文本数字化 N3 NLP中的数据集构建1. Dataset2. DataLoader N8 使用…

当代最杰出的思想家姓名学大师颜廷利:当学历与文凭突破了道德底线。。。

在当今社会&#xff0c;文凭和学历被频繁提及&#xff0c;并似乎成为了衡量个人价值的重要尺度。然而&#xff0c;当这些学术凭证超越了道德的底线时&#xff0c;整个社会便开始笼罩在谎言和欺骗的阴影之下。善良与纯真&#xff0c;如同无助的羔羊&#xff0c;在利益的屠刀下黯…

(亲测有效)SpringBoot项目集成腾讯云COS对象存储(1)

目录 一、腾讯云对象存储使用 1、创建Bucket 2、使用web控制台上传和浏览文件 3、创建API秘钥 二、代码对接腾讯云COS&#xff08;以Java为例&#xff09; 1、初始化客户端 2、填写配置文件 3、通用能力类 文件上传 测试 一、腾讯云对象存储使用 1、创建Bucket &am…

通义千问报错“撞脸”OpenAI?

笔者团队一个月前为能够使系统可以支持AI Agent的应用&#xff0c;集成了通义千问的模型接口&#xff0c;特别是集成了其可以通过推理调用外部工具的能力。并录制了相关视频如何无代码DIY一个AI Agent&#xff0c;体验还是非常不错的。 今日为客户进行该能力演示时&#xff0c;…

CAN-Linux

1.修改Makefile 然后编译 g -o hello_cpp main.cpp /home/peter/my_tool/controlcan/libcontrolcan.so -lpthread 2.查看 3.测试

2024年化工自动化控制仪表证模拟考试题库及化工自动化控制仪表理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年化工自动化控制仪表证模拟考试题库及化工自动化控制仪表理论考试试题是由安全生产模拟考试一点通提供&#xff0c;化工自动化控制仪表证模拟考试题库是根据化工自动化控制仪表最新版教材&#xff0c;化工自动化…

CSS——弹性盒(flex)

一、弹性盒的简介 1、flex&#xff08;弹性盒、伸缩盒&#xff09;&#xff1a;是css中的又一种布局手段&#xff0c;他主要用来代替浮动完成页面的布局。 2、flex可以使元素具有弹性&#xff0c;让元素可以跟随页面的大小的改变而改变。 3、弹性容器&#xff1a;要使用弹性盒&…

离谱测试!小米SU7对撞极氪007,暴露了极氪007一亮点

文 | AUTO芯球 作者 | 谦行 拿小米SU7和极氪007对撞&#xff0c;他娘的真是个人才&#xff01; 两辆车都是60km/h的速度 &#xff0c; 90%的重叠率 &#xff0c;这可比面对面撞更惨烈&#xff01; 结果&#xff0c;两辆车车头都稀烂 好在乘员舱完整&#xff0c;气囊也都弹出&…

基于808协议和1078协议的视频监控系统

卫星定位云服务平台 卫星定位云服务平台是一个车载视频终端监控系统,用于对卫星定位设备进行实时监控、实时定位、轨迹回放、指令下发、拍照记录、报警信息、实时视频、历史视频等功能。808协议和1078协议 内置功能 车队管理&#xff1a;车队信息的增删改查。型号管理&#…

2024年入职/转行网络安全,该如何规划?_网络安全职业规划

前言 前段时间&#xff0c;知名机构麦可思研究院发布了 《2022年中国本科生就业报告》&#xff0c;其中详细列出近五年的本科绿牌专业&#xff0c;其中&#xff0c;信息安全位列第一。 网络安全前景 对于网络安全的发展与就业前景&#xff0c;想必无需我多言&#xff0c;作为…