析构函数、拷贝构造
1、析构函数
析构函数的定义方式
函数名和类名相同,在类名前加~,没有返回值类型,没有函数形参(不能重载)
当对象生命周期结束的时候,系统会自动调用析构函数
先调用析构函数,再释放对象的空间
析构函数实现
#include <iostream>using namespace std;
class Person
{
private:int mAge;
public://无参构造Person(){cout<<"无参构造:"<<endl;}//无参构造Person(int age){mAge = age;cout<<"有参构造:"<<mAge<<endl;}//没有 void 和返回值~Person(){cout<<"析构函数:"<<mAge<<endl;}
};void test(){Person(20);{Person(30);}Person(40);
}int main(int argc, char *argv[])
{Person p1(10);test();return 0;
}
构造函数和析构函数的执行次序(面试题)

说白了函数从上到下执行,先执行到的先进栈,先执行有参或者无参构造,后退栈的后执行,执行析构函数
一般情况下,空的析构函数就足够,但是如果一个类有指针成员,这个类必须写析构函数,释放指针成员所指向空间
因为一个对象结束,系统默认回收的是这个对象本身的空间,但是它不会回收这个对象中指针成员指向的空间,所以如果一个类有指针成员,这个类必须写析构函数,释放指针成员所指向空间
#include <iostream>
#include <string.h>
#include <stdlib.h>using namespace std;
class Person
{
private:char *mName;
public:Person(){mName = NULL;}Person(char *name){mName = new char [strlen(name)+1]; //申请堆区空间strcpy(mName,name);cout<<"有参构造:"<<mName<<endl;}//没有 void 和返回值~Person(){if(mName != NULL){delete [] mName;cout<<"释放 Person 类的指针成员所指行向的 堆区空间"<<endl;}}
};int main(int argc, char *argv[])
{Person ml("ml");return 0;
}
最后调用析构函数释放掉 Person 类的指针成员所指行向的 堆区空间

2、拷贝构造
实现拷贝构造
//Person类中的深拷贝Person(const Person &ob){mName = new char [strlen(ob.mName)+1]; //申请堆区空间strcpy(mName,ob.mName);cout<<"有参构造:"<<ob.mName<<endl;}Person ml("ml");
Person m = ml; //深拷贝
拷贝构造本质是构造函数
在上面的代码中,旧对象给新对象初始化就会调用拷贝构造函数,ob就是旧对象的引用
系统默认的拷贝是浅拷贝,能完成基本的赋值操作,一旦实现了拷贝构造函数必须实现赋值操作,因为系统默认的函数以及无效了
const Person &ob 代表的是当前类的常引用,因为我们不希望改变参数值,所以是 const 类型的
实现深拷贝的必要性

当执行下面的代码的时候,新对象 m 中的成员指针 和 旧对象 ml 中的成员指针都会指向 堆区空间字符串为 “ml”的地址,那么 ml 在结束的时候会调用析构函数释放掉该堆区空间,而 m 在结束的时候也会调用析构函数释放掉该堆区空间
Person ml("ml");
Person m = ml; //深拷贝
所以上面的情况就是,新旧对象中的指针成员指向同一块堆区空间,于是新旧对象对同一块堆区空间释放掉了两次,造成了堆区空间的多次释放,这就是浅拷贝存在的问题
这个时候就需要使用到深拷贝,让新对象中的指针成员指向新的堆区空间,那么新旧对象释放的时候就不会多次释放同一块堆区空间,这就解决了浅拷贝存在的问题

//Person类中的深拷贝Person(const Person &ob){mName = new char [strlen(ob.mName)+1]; //新对象申请属于自己的堆区空间strcpy(mName,ob.mName);cout<<"有参构造:"<<ob.mName<<endl;}
#include <iostream>
#include <string.h>
#include <stdlib.h>using namespace std;
class Person
{
private:char *mName;
public://无参构造Person(){mName = NULL;}//有参构造Person(char *name){mName = new char [strlen(name)+1]; //申请堆区空间strcpy(mName,name);cout<<"有参构造:"<<mName<<endl;}//深拷贝Person(const Person &ob){mName = new char [strlen(ob.mName)+1]; 新对象申请属于自己的堆区空间strcpy(mName,ob.mName);cout<<"有参构造:"<<ob.mName<<endl;}//析构函数~Person(){if(mName != NULL){delete [] mName;mName = NULL;cout<<"释放 Person 类的指针成员所指行向的 堆区空间"<<endl;}}
};int main(int argc, char *argv[])
{Person ml("ml");Person m = ml; //深拷贝return 0;
}

3、注意事项
析构函数没有 void 和 返回值
如果用户定义了有参构造或者拷贝构造,都会屏蔽系统默认无参构造,所以这种情况最好是有自定义的无参构造,不会编译会出错
如果用户定义了有参构造或者无参构造,不会屏蔽拷贝构造
默认的拷贝都是浅拷贝(能完成基本的操作)
如果类中没有指针成员,不用实现构造拷贝和析构函数
如果类中有指针成员而且指向堆区空间,必须实现析构函数释放指针成员指向的堆区空间,必须实现拷贝构造完成深拷贝动作
相关文章:

析构函数、拷贝构造
1、析构函数析构函数的定义方式函数名和类名相同,在类名前加~,没有返回值类型,没有函数形参(不能重载)当对象生命周期结束的时候,系统会自动调用析构函数先调用析构函数,再释放对象的空间析构函…...
光学镜头是制作过程阶段理解
光学镜头是由多组镜片组合而成,它是摄影机投影一及显微镜上必不可少的部件。那么光学镜头是如何制造的呢?光学镜头的制作分为以下四个阶段:第一、首先将一大块光学玻璃用钻石锯片进行切片,然后用钻头在每一块玻璃切片上钻出多块冰…...

实验室设计|实验室设计要点SICOLAB
一、实验室设计规划要素1、实验室布局:实验室的布局要符合实验室工作流程,可以将实验室划分为干净区和污染区,以确保实验室的卫生和实验的准确性。2、设备选购:根据实验需要选择适当的设备,并确保设备的质量和性能符合…...

I.MX6ULL_Linux_系统篇(16) uboot分析-启动流程
原文链接:I.MX6ULL_系统篇(16) uboot分析-启动流程 – WSY Personal Blog (cpolar.cn) 前面我们详细的分析了 uboot 的顶层 Makefile,了解了 uboot 的编译流程。本章我们来详细的分析一下 uboot 的启动流程,理清 uboot 是如何启动的。通过对 …...

【C#】async关键字修饰后有无await的影响
文章目录测试总结拓展:js的async await问题参考测试 来自微软官网的说法: 异步方法通常包含 await 运算符的一个或多个匹配项,但缺少 await 表达式不会导致编译器错误。 如果异步方法未使用 await 运算符标记悬挂点,则该方法将作…...

Interspeech2022 | 一种基于元辅助学习的低资源口语语义理解方法
中国移动研究院首席科学家冯俊兰博士带领人工智能与智慧运营中心语音团队共同撰写的文章《Meta Auxiliary Learning for Low-resource Spoken Language Understanding》被语音国际顶会Interspeech2022接收。 关于Interspeech Interspeech 是国际最大且最全面关于言语科学与技…...

File类的用法和InputStream,OutputStream的用法
这里写自定义目录标题一、File类1.构造方法2.普通方法二、InputStream1.方法2.FileInputStream3.Scanner类的应用三、OutputStream1.方法2.FileOutputStream3.PrintWriter类的应用一、File类 1.构造方法 签名说明File(File parent, Stringchild)根据父目录 孩子文件路径&…...
Java多线程——Thread类的基本用法
一.线程的创建继承Thread类//继承Thread类class MyThread extends Thread{Overridepublic void run() {System.out.println("线程运行的代码");} } public class Demo1 {public static void main(String[] args) {MyThread t new MyThread();t.start();//启动线程&a…...

【C++】类和对象练习——日期类的实现
文章目录前言1. 日期的合法性判断2. 日期天数(/)2.1 和的重载2.2 对于两者复用的讨论3. 前置和后置重载4. 日期-天数(-/-)5. 前置- -和后置- -的重载6. 日期-日期7. 流插入<<重载8. 流提取>>重载9. 总结10. 源码展示前…...

[LeetCode周赛复盘] 第 333 场周赛20230219
[LeetCode周赛复盘] 第 333 场周赛20230219 一、本周周赛总结二、 [Easy] 6362. 合并两个二维数组 - 求和法1. 题目描述2. 思路分析3. 代码实现三、[Medium] 6365. 将整数减少到零需要的最少操作数1. 题目描述2. 思路分析3. 代码实现四、[Medium] 6364. 无平方子集计数1. 题目描…...

数字化时代,如何做好用户体验与应用性能管理
引言 随着数字化时代的到来,各个行业的应用系统从传统私有化部署逐渐转向公有云、行业云、微服务,这种变迁给运维部门和应用部门均带来了较大的挑战。基于当前企业 IT 运维均为多部门负责,且使用多种运维工具,因此,当…...

Python爬虫(7)selenium3种弹窗定位后点击操作,解决点击登录被隐藏iframe无法点击的登陆问题
之前的文章有关于更多操作方式详细解答,本篇基于前面的知识点进行操作,如果不了解可以先看之前的文章 Python爬虫(1)一次性搞定Selenium(新版)8种find_element元素定位方式 Python爬虫(2)-Selenium控制浏览…...

如何对项目健康度进行测量?评估项目健康状况
项目驱动变革,大部分公司逐步由运营驱动转变为项目驱动,带来更多重新和商业价值。对组织而言,从商业角度看,项目旨在推动组织从一个状态转到另一个状态,从而达成特定目标。项目的健康情况如何关乎项目和变革的成本&…...

美国原装二手keysight E4980A(安捷伦)2MHZ LCR表
Agilent E4980A、Keysight E4980A、LCR 表,20 Hz - 2 MHz E4980A 是 Agilent 的 2 MHz LCR 表。LCR表是一种电子测试设备,用于测量电子元件的电感(L)、电容(C)和电阻(R)。LCR 表可…...
《clean coder》:关于摆烂,争论和心态
“凡是不能在五分钟之内解决的争论,都不能依靠辩论解决” ---- Kent Beck 作为一个码农,我并不是一个喜欢争论的角色。很长一段时间会陷入一种摆烂的,被动的状态。“既然其他人想要这么做,就这么办吧”。这可能是非专业的行为中最…...

jenkins下载与简单使用
1.jenkins下载 因为我仍然使用的是jdk1.8进行开发,所以我下载的是jenkins2.332.1版本(jenkins2.346.1版本在2022年末不再支持java8,如果项目使用的是jdk11可以继续使用该jenkins版本),更多版本下载请点击jenkins下载 …...

3|物联网控制|计算机控制-刘川来胡乃平版|第3章:计算机总线技术 补充串行总线部分|课堂笔记|ppt
2022年 10月 10日 3.3 外部总线 3.3.2 RS-232-C总线 机械特性...

Blazor入门100天 : 身份验证和授权 (3) - DB改Sqlite
目录 建立默认带身份验证 Blazor 程序角色/组件/特性/过程逻辑DB 改 Sqlite将自定义字段添加到用户表脚手架拉取IDS文件,本地化资源freesql 生成实体类,freesql 管理ids数据表初始化 Roles,freesql 外键 > 导航属性完善 freesql 和 bb 特性 本节源码 https://github.com/…...

阅读源码和查看官方文档,是解决问题最高效的办法。
作为一个工作8年的老程序员告诉你:阅读源码和查看官方文档,是解决问题最高效的办法。不信你来看,这个困扰了读者半天的问题我查了源码和文档后瞬间解决。 前言 上周五有位读者私信我一个问题,说困扰了他半天,研究了一…...
云原生流量管理系统中 Service , Ingress 和 Endpoint 的关系
摘要 Kubernetes(简称 K8s)是一个用于容器编排和管理的开源平台,其中流量管理是 K8s 的重要功能之一。K8s 提供了多种流量管理方式,以便对不同场景下的流量进行控制和管理。以下是 K8s 中常用的流量管理系统: Service:Service 是 K8s 中最基本的流量管理方式,用于提供…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...

(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...