详解构造函数和析构函数

⼀个类,我们不写的情况下编译器会默认⽣成以下6个默认成员函数。
在这里插入图片描述
下面我们详细介绍的是构造函数析构函数,它们的主要作用分别是初始化工作清理工作

构造函数

1、构造函数的概念

构造函数虽名里带着“构造”但是其实际上并不是说开辟空间创建对象,而是对象实例化的时候初始化。保证每个数据成员都有一个合适的初始值,并且在对象的生命周期内只调用一次。这也方便我们不需要初始化。
下面我们可以看这个代码:

#define  _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;class Date {
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};int main()
{Date d;d.Init(2025, 1, 19);d.Print();return 0;
}

我们可以看这个代码正常情况下:
在这里插入图片描述
可是当我们忘记初始化的时候:
在这里插入图片描述
从上述图片我们可以看到,运行结果输出了一串随机值

2、构造函数的特性

1.函数名和类名相同
2.没有返回值
3.对象实例化时系统会⾃动调⽤对应的构造函数
4.构造函数可以重载
5.类中没有显式定义构造函数,编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成
6.无参构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。我们没写编译器默认生成的构造函数都可以认为是默认成员函数。
7.我们不写,编译器默认⽣成的构造,对内置类型成员变量的初始化没有要求,也就是说是是否初始化是不确定的,看编译器。对于⾃定义类型成员变量,要求调⽤这个成员变量的默认构造函数初始化。

#define  _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;class Date {
public://无参构造函数/*Date(){_year = 1;_month = 1;_day = 1;}*///带参构造函数Date(int year, int month, int day){_year = year;_month = month;_day = day;}//全缺省构造函数Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};int main()
{Date d; //调用默认构造函数Date d1(2025, 1, 19); //调用带参构造函数//d.Init(2025, 1, 19);d.Print();return 0;
}

构造函数支持函数重载

在这里插入图片描述

如果类中没有显式定义构造函数,则编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。
下面我们来看一下这个代码:

#define  _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;class Date {
public://全缺省构造函数/*Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}*/void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};int main()
{Date d;d.Print();return 0;
}

我们将上述代码运行会发现出现的是随机数,这是为什么呢?上面不是说了没有显式定义构造函数,编译器会自动生成一个无参的默认构造函数吗?为什么会出现是随机数呢?
在这里插入图片描述
这个是因为C++默认生成的构造函数对内置类型成员变量不做处理,但是对于自定义类型的成员变量才会处理。这就是为什么上面会出现随机数的情况了
那么哪种是自定义类型,哪种是内置类型呢?
内置类型是:int、char等
自定义类型就是:class、struct去定义的类型对象

下面我们再看这一串代码:

class Stack {
public:Stack(){A = nullptr;top = capacity;}
private:int* A;int top;int capacity;
};class _Queue {
public:void push(int n){}
private:Stack s1;Stack s2;
};

我们可以看到s1和s2就不需要初始化了直接就默认生成的。但是如果是栈里面没有写构造函数,那么就会像上面一样出现随机值,因为栈里面的是内置类型。

综上所述,我们可以知道如果是一个类中的成员全是自定义类型,我们就可以用默认生成的函数。如果有内置类型的成员,或者需要显示传参初始化的,那么就要自己实现构造函数。

假设我们不想写构造类型也要对内置类型处理呢?

#define  _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;class Date {
public://全缺省构造函数/*Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}*/void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year = 2025;int _month = 1;int _day = 19;
};int main()
{Date d;d.Print();return 0;
}

在这里插入图片描述
使用默认构造函数提前给成员变量定义好

析构函数

析构函数的概念

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

析构函数的特性

1.析构函数名是在类名前面加上符号"~"
2.无参数返回值(这个第二点和构造函数一样)
3.一个类有且仅有一个析构函数。若未显式定义,系统会⾃动⽣成默认的析构函数。
4.对象生命周期结束时,编译器系统自动调用析构函数。
5.编译器生成的默认析构函数,对会自定类型成员调用它的析构函数。

下面我们还是用日期类的代码举例:

class Date {
public:Date(int year = 2025, int month = 1, int day = 19){_year = year;_month = month;_day = day;}void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}~Date(){cout << "~Date()" << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d; //调用默认构造函数d.Print();return 0;
}

在这里插入图片描述
我们可以看到d会调用它的默认构造函数进行初始化,出了作用域后又调用其析构函数。

析构函数是完成对资源的清理,那什么才算是清理呢?答案是:对malloc、new、fopen这些进行清理。

class Stack
{
public:Stack(int n = 4){_a = (STDataType*)malloc(sizeof(STDataType) * n);if (nullptr == _a){perror("malloc申请空间失败");return;}_capacity = n;_top = 0;}~Stack(){cout << "~Stack()" << endl;free(_a);_a = nullptr;_top = _capacity = 0;
}
private:STDataType* _a;size_t _capacity;size_t _top;
};
int main()
{Stack s;
}

我们看下面这个代码:

int main()
{Stack s1;Stack s2;
}

如果是上述两个实例化对象,s1先构造呢还是s2先构造,又或者s1先析构还是s2先析构?
答案是:前者是s1先构造,后者是s2先析构。
后者为什么是s2先析构呢?这个就好比是在栈上,后进先出,s2后压栈,那它肯定是先出的。

析构函数和构造函数是一样的,对内置类型不处理,自定义类型会去调用它的析构函数。

综上所述,如果在类没有申请资源的时候析构函数是可以不用写的,直接让编译器生成默认析构函数。有资源的时候是一定要写的,否则会造成资源泄露。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

go语言zero框架通过chromedp实现网页在线截图的设计与功能实现

在 GoZero 框架中实现网页在线截图的功能&#xff0c;可以通过集成 chromedp 库来控制 Chrome 浏览器进行截图。chromedp 是一个基于 Chrome DevTools 协议的 Go 包&#xff0c;可以用来在 Go 程序中模拟浏览器操作&#xff0c;如页面截图、DOM 操作、表单提交等。 下面是一个…

【Django开发】django美多商城项目完整开发4.0第12篇:商品部分,表结构【附代码文档】

本教程的知识点为&#xff1a; 项目准备 项目准备 配置 1. 修改settings/dev.py 文件中的路径信息 2. INSTALLED_APPS 3. 数据库 用户部分 图片 1. 后端接口设计&#xff1a; 视图原型 2. 具体视图实现 用户部分 使用Celery完成发送 判断帐号是否存在 1. 判断用户名是否存在 后…

HarmonyOS应用开发-低代码开发登录页面(超详细)

本篇文章我来手把手教大家做一个HarmonyOS 应用的登录页面&#xff0c;逐步讲解&#xff0c;非常细致&#xff0c;百分百能学会&#xff0c;并提供全部源码。页面使用 DevEco Studio 的低代码开发。 通过本文的实践经验&#xff0c;我想告诉大家&#xff0c; HarmonyOS 应用开发…

Reactive StreamsReactor Core

Reactive Streams&Reactor Core 一、概述1、问题2、优势3、发展 二、Reactive Streams1、依赖2、API 三、Project Reactor1、概述2、并发模型3、入门1&#xff09;依赖2&#xff09;Flux和Mono3&#xff09;空流&错误流 4、订阅响应式流1&#xff09;常见订阅2&#xf…

【数据分享】1929-2024年全球站点的逐日平均气温数据(Shp\Excel\免费获取)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、湿度等指标&#xff0c;其中又以气温指标最为常用&#xff01;说到气温数据&#xff0c;最详细的气温数据是具体到气象监测站点的气温数据&#xff01;本次我们为大家带来的就是具体到气象监…

简单介绍JSONStream的使用

地址 作用 这个模块是根据需要筛选出json数据中自己所需要的数据 使用 var JSONStream require("JSONStream"); var parse require("fast-json-parse"); var fs require("fs");fs.createReadStream("./time.json").pipe(JSONSt…

信息奥赛一本通 1168:大整数加法

这道题是一道大整数加法&#xff0c;涉及到高精度的算法&#xff0c;比如说有两个数要进行相加&#xff0c;1111111111111111111111111111111111111112222222222222222222222222222222&#xff0c;那么如果这两个数很大的话我们常用的数据类型是不能进行计算的&#xff0c;那么…

架构思考与实践:从通用到场景的转变

在当今复杂多变的商业环境中&#xff0c;企业架构的设计与优化成为了一个关键议题。本文通过一系列随笔&#xff0c;探讨了业务架构的价值、从通用架构到场景架构的转变、恰如其分的架构设计以及如何避免盲目低效等问题。通过对多个实际案例的分析&#xff0c;笔者揭示了架构设…

[JavaScript] 运算符详解

文章目录 算术运算符&#xff08;Arithmetic Operators&#xff09;注意事项&#xff1a; 比较运算符&#xff08;Comparison Operators&#xff09;注意事项&#xff1a; 逻辑运算符&#xff08;Logical Operators&#xff09;短路运算&#xff1a;逻辑运算符的返回值&#xf…

Java测试开发平台搭建(九)前端

1. 搭建前端vue环境 Vue3 安装 | 菜鸟教程 2. 创建项目 1.进入ui vue ui 2. create项目 3. 成功之后添加插件&#xff1a; cli-plugin-router vue-cli-plugin-vuetify 4. 添加依赖 axios 5. 点击任务开始运行 如果报错&#xff1a; 修改vue.config.jsconst { defineConfig }…

【Linux系统编程】—— 深度解析进程等待与终止:系统高效运行的关键

文章目录 进程创建再次认识fork()函数fork()函数返回值 写时拷贝fork常规⽤法以及调用失败的原因 进程终⽌进程终止对应的三种情况进程常⻅退出⽅法_exit函数exit函数return退出 进程等待进程等待的必要性进程等待的⽅法 进程创建 再次认识fork()函数 fork函数初识&#xff1…

最新版Edge浏览器加载ActiveX控件技术——allWebPlugin中间件之awp_CreateActiveXObject接口用法

背景 ActiveXObject‌是JavaScript中的一个特殊对象&#xff0c;用于在Internet Explorer&#xff08;IE&#xff09;浏览器中创建和操作COM&#xff08;Component Object Model&#xff09;对象。COM是一种面向对象的软件组件技术&#xff0c;允许不同应用程序之间的互操作性。…

使用 Java 和 FreeMarker 实现自动生成供货清单,动态生成 Word 文档,简化文档处理流程。

在上一篇博客中主要是使用SpringBootApache POI实现了BOM物料清单Excel表格导出&#xff0c;详见以下博客&#xff1a; Spring Boot Apache POI 实现 Exc&#xff08;&#xff09;el 导出&#xff1a;BOM物料清单生成器&#xff08;支持中文文件名、样式美化、数据合并&#…

JS基础(5):运算符和语句

一.运算符 1.赋值运算符 加减乘除都是一样的&#xff0c;&#xff0c;-&#xff0c;*&#xff0c;/ 2.一元运算符&#xff1a;经常用来计数 自增&#xff1a; 每次只能加一 自减&#xff1a;-- 前置自增 后置自增 结…

以租赁合同的例子讲清楚 开源协议原理和区别

开源协议通俗易懂的方式介绍清楚原理和区别 开源协议其实就是软件的“使用规则”&#xff0c;决定了别人可以如何使用、修改、分享你的代码。通俗一点说&#xff0c;如果你写了一段代码&#xff0c;开源协议就是告诉别人在什么条件下他们可以使用你的代码&#xff0c;以及他们可…

Flowable 管理各业务流程:流程设计器 (获取流程模型 XML)、流程部署、启动流程、流程审批、流程挂起和激活、任务分配

文章目录 引言I 表结构主要表前缀及其用途核心表II 流程设计器(Flowable BPMN模型编辑器插件)Flowable-UIvue插件III 流程部署部署步骤例子:根据流程模型ID部署IV 启动流程启动步骤ACT_RE_PROCDEF:流程定义相关信息例子:根据流程 ID 启动流程V 流程审批审批步骤Flowable 审…

【C++课程学习】:C++中的IO流(istream,iostream,fstream,sstream)

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;C课程学习 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 C学习笔记&#xff1a; https://blog.csdn.net/djdjiejsn/category_12682189.html 前言&#xff1a; 在C语…

四、华为交换机 STP

生成树协议&#xff08;STP&#xff09;的核心目的是在存在冗余链路的网络中&#xff0c;构建一个无环的拓扑结构&#xff0c;从而防止网络环路带来的广播风暴等问题 一、STP 原理 选举根桥&#xff1a;网络中的每台交换机都会有一个唯一的桥 ID&#xff08;BID&#xff09;&am…

数字图像处理:实验二

任务一&#xff1a; 将不同像素&#xff08;32、64和256&#xff09;的原图像放大为像素大 小为1024*1024的图像&#xff08;图像自选&#xff09; 要求&#xff1a;1&#xff09;输出一幅图&#xff0c;该图包含六幅子图&#xff0c;第一排是原图&#xff0c;第 二排是对应放大…

综述:大语言模型在机器人导航中的最新进展!

简介 机器人导航是指机器人能够在环境中自主移动和定位的能力。本文系统地回顾了基于大语言模型&#xff08;LLMs&#xff09;的机器人导航研究&#xff0c;将其分为感知、规划、控制、交互和协调等方面。具体来说&#xff0c;机器人导航通常被视为一个几何映射和规划问题&…