C++类和对象:构造函数和析构函数
目录
一. 类的六个默认成员函数
二. 构造函数
2.1 什么是构造函数
2.2 编译器自动生成的默认构造函数
2.3 构造函数的特性总结
三. 析构函数
3.1 什么是析构函数
3.2 编译器自动生成的析构函数
3.3 析构函数的特性总结
一. 类的六个默认成员函数
对于任意一个C++类,如果用户不定义任何成员函数,那么编译器就会自动生成6个默认成员函数。当然,这6个成员函数也可以由用户自主定义,如果用户自主定义了,那么系统就不会自动生成。这6个默认成员函数包括:构造函数、析构函数、拷贝构造函数、赋值重载函数、对普通对象和const对象的取地址重载函数。

二. 构造函数
2.1 什么是构造函数
构造函数在定义类对象是由编译的自动调用,用于初始化类的成员变量。构造函数是一种十分特殊的成员函数,它没有返回值,它的函数名与类名相同。
任何一个类都不能没有默认构造函数,否则这个类就是非法的,在用这个类初始化对象时编译器会报错。默认构造函数,就是不需要参数就可以调用的构造函数,默认构造函数有三种可能的形式:
- 无参数
- 全缺省参数
- 由编译器自动生成的构造函数
演示代码2.1定义了一个日期类,并定义了一个全缺省的构造函数,这里由于用户自定义了构造函数,所有编译器不会生成默认构造函数。此外,还应当明确,构造函数是支持重载的,Date(int year = 1, int month = 1, int day = 1)可以被拆分为一个无参的构造函数Date()和一个不存在确实参数的构造函数Date(int year, int month, int day)。
演示代码2.1:
class Date //日期类
{
public:Date(int year = 1, int month = 1, int day = 1) //自定义默认构造函数{_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}private:int _year;int _month;int _day;
};int main()
{//定义类对象,调用默认构造函数Date d1; //Date(1, 1, 1)Date d2(2023, 2, 26); //Date(2023, 2, 26)d1.Print(); //1-1-1d2.Print(); //2023-2-26return 0;
}

2.2 编译器自动生成的默认构造函数
当用户不自定义默认构造函数时,编译器就会自动生成默认构造函数,编译的自动生成的构造函数进行的工作为:
- 对于内置类型成员变量,不进行初始化
- 对于自定义类型成员变量,调用自定义类型成员变量的默认构造函数
其中,内置类型指int、char、double、float、指针、内置类型数组等C/C++自带的数据类型,自定义类型指使用struct/class定义的类或结构体数据类型。
为了验证编译器自动生成的构造函数所完成的功能,在演示代码2.2中定义了一个Date类和一个Time类,在Date类中不自定义构造函数,在Time类中定义默认构造函数将Time中的成员变量全部初始化为1,Date类中包括3个内置类型成员变量和1个Time类类型的成员变量。对程序进行调试,可见定义好的Date类对象d1中的内置类型成员变量都是随机值,而d1中的类对象t的成员变量都变变为了1。这就证实了上面对编译的自动生成的构造函数进行的工作的讲述的正确性。
演示代码2.2:
class Time
{
public:Time(int hour = 1, int minute = 1, int second = 1) //自定义默认构造函数{_hour = hour;_minute = minute;_second = second;}private:int _hour;int _minute;int _second;
};class Date
{
private:int _year;int _month;int _day;Time t;
};int main()
{Date d1; //定义类对象,调用编译器自动生成的默认构造函数return 0;
}

我们可以认为默认构造函数不对内置类型成员变量做任何处理是C++的一个缺陷。为了弥补这一缺陷, C++11允许在定义类是显示的声明内置类型成员变量的初值。如演示代码2.3所示,Date类中的三个成员变量都被赋默认初值1。
演示代码2.3:
class Date
{
public:void Print(){cout << _year << "-" << _month << "-" << _day << endl;}private:int _year = 1;int _month = 1;int _day = 1; //三个内置类型的成员变量的默认初值都为1(C++11)
};int main()
{Date d;d.Print(); //1-1-1return 0;
}
2.3 构造函数的特性总结
- 构造函数是特殊的成员函数,函数名与类名相同,无返回值。
- 构造函数在对象实例化时由编译器自主调用,无需用户手动调用。
- 构造函数可以重载。
- 如果用户不显示定义构造函数,那么编译器就会生成默认的构造函数。
三. 析构函数
3.1 什么是析构函数
析构函数的功能与构造函数相反,在类对象生命周期结束时,由编译器自动调用,完成对类对象的资源清理工作,析构函数的函数名为:~类名。
析构函数可以由用户自身定义,也可以由编译器自主生成。当拥护显示的定义了析构函数时,编译器不自动生成析构函数,但当用户不显示的定义析构函数时,编译器会自动生成默认的析构函数。
析构函数没有参数、没有返回值。
演示代码3.1定义了一个简易的栈类Stack,其中定义了三个成员变量:int* _a -- 存储栈数据的数组、int _top -- 栈顶位置下标、int _capacity -- 栈容量,还定义了四个成员函数:Stack -- 栈初始化函数(构造函数)、Push -- 压栈函数、Print -- 栈中数据打印函数、~Stack -- 栈销毁函数(析构函数)。在~Stack函数中释放了动态开辟的内存。
在主函数中,我们创建了一个栈类对象S,程序的运行结果表明,构造函数和析构函数先后被调用。
演示代码3.1:
class Stack
{
public:Stack(int capacity = 3) //构造函数,初始化栈,类实例化时自动调用{cout << "Stack()" << endl;_a = (int*)malloc(capacity * sizeof(int)); //为栈数组动态开辟内存空间if (nullptr == _a){cout << "malloc fail" << endl;exit(-1);}_capacity = capacity;_top = 0;}void Push(int x) //压栈函数,x为压入数据{if (_top == _capacity) //检查栈是否已满{int* tmp = (int*)realloc(_a, (_capacity * 2) * sizeof(int)); //开辟新的内存空间if (tmp == nullptr){cout << "realloc fail" << endl;}_a = tmp;_capacity *= 2;}_a[_top++] = x;}void Print() //栈中数据打印函数{for (int i = 0; i < _top; ++i){cout << _a[i] << " ";}cout << endl;}~Stack() //析构函数,在对象生命周期结束时自动调用{cout << "~Stack()" << endl;free(_a); //释放栈空间_a = nullptr;_top = _capacity = 0;}private:int* _a; //存储栈数据的数组int _top; //栈顶下标int _capacity; //栈容量
};int main()
{Stack S; //类实例化,调用默认构造函数S.Push(1);S.Push(2);S.Push(3);S.Push(4);S.Push(5); //将1、2、3、4、5压入栈中S.Print(); //打印栈中数据return 0; //对象生命周期结束,调用析构函数
}

3.2 编译器自动生成的析构函数
如果用户不显示定义析构函数,则编译器会生成默认的析构函数,编译器自动生成的析构函数所执行的操作与编译器自动生成的构造函数类似:
- 对于内置类型成员变量,不做任何处理。
- 对于自定义类型成员变量,去掉它的析构函数。
演示代码3.2定义了一个名为TwoStack的类,其中包含两个Stack类的自定义类型成员变量S1和S2,在主函数中对类进行实例化,创建对象ts,在ts创建和销毁时都调用Stack的默认构造函数和析构函数。
演示代码3.2:
class TwoStack
{
private:Stack S1;Stack S2;
};int main()
{TwoStack st; //类实例化,调用默认构造函数return 0; //对象生命周期结束,调用析构函数
}

问题:什么时候可以使用编译器自动生成的析构函数,什么时候必须显示定义析构函数?
- 当类中的成员变量仅在栈区占用内存空间时,类对象的生命周期结束是成员变量所占用的空间自动被释放,不需要析构函数执行额外的操作,如日期类Date,就不需要自定义析构函数。
- 当类的成员变量执行堆区开辟的某一块空间时,如通过malloc动态开辟了内存空间,就需要显示的定义析构函数来进行资源清理,如Stack类就不能使用编译器自动生成的析构函数。
3.3 析构函数的特性总结
- 析构函数的函数名是在类名前面加~。
- 析构函数无参数、无返回值。
- 析构函数在类对象生命周期结束时由编译器自主调用。
- 一个类有且只有一个析构函数,要么由用户显示定义,要么由编译器自动生成。
- 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类。
相关文章:

C++类和对象:构造函数和析构函数
目录 一. 类的六个默认成员函数 二. 构造函数 2.1 什么是构造函数 2.2 编译器自动生成的默认构造函数 2.3 构造函数的特性总结 三. 析构函数 3.1 什么是析构函数 3.2 编译器自动生成的析构函数 3.3 析构函数的特性总结 一. 类的六个默认成员函数 对于任意一个C类&…...

【Stata】从入门到精通.零基础小白必学的教程,一学就fei
视频教程移步:https://www.bilibili.com/video/BV1hK4y1d714/?p4&spm_id_frompageDriver&vd_sourcecc8074e9c81a225f214226065db53d32P3 第二讲 Stata处理数据全流程(上) P3 - 01:37内置数据 file example datasets使用…...
【RuoYi优化】调整JVM启动内存
📔 笔记介绍 大家好,千寻简笔记是一套全部开源的企业开发问题记录,毫无保留给个人及企业免费使用,我是作者星辰,笔记内容整理并发布,内容有误请指出,笔记源码已开源,前往Gitee搜索《chihiro-notes》,感谢您的阅读和关注。 作者各大平台直链: GitHub | Gitee | CSD…...
[架构模型]MVC模型详细介绍,并应用到unity中
简介: MVC模式是一种软件架构模式,它将应用程序分为三个主要部分:模型(Model)、视图(View)和控制器(Controller)。MVC模式的目标是实现应用程序的松耦合,以便…...

?? JavaScript 双问号(空值合并运算符)
?? JavaScript 双问号(空值合并运算符) 一、简述 在网上浏览 JavaScript 代码时或者学习其他代码时,可能会发现有的表达式用了两个问号(??)如下所示: let username; console.log(username ?? "Guest"…...

作业2.25----通过操作Cortex-A7核,串口输入相应的命令,控制LED灯进行工作
1.通过操作Cortex-A7核,串口输入相应的命令,控制LED灯进行工作 例如在串口输入led1on,开饭led1灯点亮 2.例如在串口输入led1off,开饭led1灯熄灭 3.例如在串口输入led2on,开饭led2灯点亮 4.例如在串口输入led2off,开饭led2灯熄灭 5.例如在串口输入led…...

0101基础概念-图-数据结构和算法(Java)
文章目录1 图1.1 定义1.2 4种图模型2 无向图2.1 定义2.2 术语后记1 图 1.1 定义 图是一种非线性的数据结构,表示多对多的关系。 图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V, E)…...

Linux基础命令和工具使用详解
Linux基础命令和工具使用详解一、grep搜索字符二、find查找文件三、ls 显示文件四、wc命令计算字数五、uptime机器启动时间负载六、ulimit用户资源七、curl http八、scp远程拷贝九、dos2unix和unix2dos十、sed 行处理10.1、简单模式10.2、替换模式十一、awk 列处理11.1、打印某…...

一个好的python文件可以有几种用途?
大家好鸭!我是小熊猫~ 这次来带大家浅浅回顾一点python小知识~ 源码资料电子书:点击此处跳转文末名片获取 python文件总共有两种用途: 一种是执行文件另一种是被当做模块导入 编写好的一个python文件可以有两种用途: 1. 脚本,…...

HDFS优化
单节点多块磁盘数据均衡 生成HDFS块均衡计划 hdfs diskbalancer -plan node1 执行均衡计划,node1.plan.json均衡计划文件 hdfs diskbalancer -execute node1.plan.json 查看当前均衡任务的执行情况 hdfs diskbalancer -query node1 取消均衡任务hdfs diskbalancer -cancel nod…...

行测-判断推理-图形推理-样式规律-黑白运算
黑白元素个数不同,优先考虑黑白运算白白白黑黑白黑白黑选A考试时,这种题不要先把规律全部推出来,再去做题,太慢了直接看要推的图,通过排除法选答案黑白元素个数不同,优先考虑黑白运算白白白黑黑白黑白黑选B…...

java+springboot+vue高校学生医疗保险管理系统
医保管理系统是对与职工健康息息相关的档案进行的系统化、自动化的管理,主要是对职工办理的医疗保险的管理,本系统能够很好的适应社会的需求,最大化的为城镇职工提供服务。医疗保险是国家社会保障体系的重要组成部分,也是社会保险…...
[已解决] AHK 映射 ESC 延迟 500 ms 的严重问题
问题描述 今天发现一个重大bug,我竟然用了一年多都不知道! CapsLock::Esc 我的 ahk 脚本将 capslock 映射为 esc,但这在vim环境中,估算响应 500ms。 也就说按下 caps 键,还要等一会,才进入normal模式 如果…...
QML state详解
1.state简介 changes(list<Change>):保存当前State下的多个Change对象,比如PropertyChanges、StateChangeScript、ParentChange等。 extend(string):表示该状态要在哪个State的基础上进行扩展,当一个…...

一起Talk Android吧(第五百零六回:如何调整组件在约束布局中的角度)
文章目录背景介绍相关属性使用方法示例程序各位看官们大家好,上一回中咱们说的例子是"如何调整组件在约束布局中的大小",这一回中咱们说的例子是"如何调整组件在约束布局中的角度"。闲话休提,言归正转, 让我们一起Talk A…...

微信投票-课后程序(JAVA基础案例教程-黑马程序员编著-第七章-课后作业)
【实验7-5】 微信投票 【任务介绍】 1.任务描述 如今微信聊天已经普及到几乎每一个人,在聊天中,经常会有人需要帮忙在某个APP中投票。本案例要求编写一个模拟微信投票的程序,通过在控制台输入指令,实现添加候选人、查看当前投票…...

duboo+zookeeper分布式架构入门
分布式 dubbo Zookeeper 分布式系统就是若干独立计算机的集合(并且这些计算机之间相互有关联,就像是一台计算机中的C盘F盘等),这些计算对于用户来说就是一个独立的系统。 zookeeper安装 下载地址:Index of /dist/z…...

黑盒测试用例设计方法-等价类划分法
目录 一、等价类的作用 二、等价类的分类 三、等价类的方法 四、等价类的原则 五、按照测试用例的完整性划分等价类 六、等价类步骤 七、案例 一、等价类的作用 为穷举测试设计测试点。 穷举:列出所有的可能情况,对其一一判断。 测试点&#x…...

4.OCR文本识别Connectionist Temporal Classification(CTC)算法
文章目录1.基础介绍2.Connectionist Temporal Classification(CTC)算法2.1 什么是Temporal Classification2.2 CTC问题描述2.2关于对齐2.3 前向后向算法2.4 推理时3.pytorch中的CTCLOSS参考资料欢迎访问个人网络日志🌹🌹知行空间🌹dz…...
误删了Ubuntu/Linux的一些默认用户目录怎么办?
用户目录:指位于 $HOME 下的一系列常用目录,例如 Documents,Downloads,Music,还有 Desktop等。本文不是讲如何恢复原有目录及其重要文件,适用于仅恢复目录功能一:仅恢复个别目录如误删了Desktop…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...

wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...
pycharm 设置环境出错
pycharm 设置环境出错 pycharm 新建项目,设置虚拟环境,出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...

ubuntu22.04有线网络无法连接,图标也没了
今天突然无法有线网络无法连接任何设备,并且图标都没了 错误案例 往上一顿搜索,试了很多博客都不行,比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动,重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...
LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)
在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...