类和对象【三】析构函数和拷贝构造函数

news/2024/5/10 2:32:09

文章目录

  • 析构函数
    • 析构函数的定义
    • 析构函数的作用
      • 主要作用
      • 次要作用
    • 析构函数的特点
  • 拷贝构造函数
    • 拷贝构造函数的定义
    • 拷贝构造函数的作用
      • 主要作用
      • 次要作用
    • 拷贝构造函数的特点
    • 浅拷贝和深拷贝
      • 浅拷贝
      • 深拷贝
    • 拷贝构造函数的调用场景

析构函数

析构函数的定义

析构函数(destructor) 与构造函数相反,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统自动执行析构函数。
析构函数往往用来做“清理善后” 的工作(例如:在建立对象时用new开辟了一片内存空间,delete会自动调用析构函数后释放内存)。
来自百度百科


析构函数的作用

主要作用

完成对 对象 申请来的资源清理工作

析构函数可以用于释放对象在使用过程中分配的资源,如动态分配的内存打开的文件句柄网络连接
这样可以避免资源泄漏,确保程序的稳定性和资源的有效管理


次要作用

可以根据析构函数在对象生命周期结束时编译器自动调用这个特点,在析构函数中完成一些特殊操作

【例如:在类里创建一个static修饰的成员变量,让它在调用构造函数时++,调用拷贝构造时++,调用析构函数时- -,这样就可以实时记录还有多少个“存活”】


析构函数的特点

  1. 析构函数名是在类名前加上字符 。

  2. 析构函数没有参数也返回值类型。

  3. 对象生命周期结束时编译器自动调用析构函数

  4. 因为析构函数没有参数,所以析构函数不能重载,所以一个类只有一个析构函数

  5. 如果没有显式实现析构函数,编译器会自动生成一个默认的析构函数
    这个默认的析构函数的特点是:
    1 对内置类型成员变量不做处理无论内置类型是否申请了资源,都不处理
    2 对自定义类型 就自动调用所属的类的析构函数

    在这里插入图片描述


拷贝构造函数

拷贝构造函数的定义

拷贝构造函数是C++中一种构造函数的重载,它的作用是:用已有对象创建一个新对象,并将已存在的同类对象的数据成员拷贝到新对象中。
拷贝构造函数的形参是一个对该已有对象的引用,并且通常会被声明为const,以防止通过引用修改原对象


拷贝构造函数的作用

主要作用

用已有对象创建一个新对象,并将已存在的同类对象的数据成员拷贝到新对象中。

次要作用

可以根据拷贝构造函数在创建对象时编译器自动调用这个特点,在析构函数中完成一些特殊操作

【例如:在类里创建一个static修饰的成员变量,让它在调用构造函数时++,调用拷贝构造时++,调用析构函数时- -,这样就可以实时记录还有多少个“存活”】


拷贝构造函数的特点

  1. 拷贝构造函数是构造函数的重载,所以它也是构造函数,它只能用于创建新对象不能用于两个已经创建对象之间的拷贝

  2. 拷贝构造函数只有一个参数,参数必须是该类的对象的引用
    如果第不是该类的对象的引用或者有多个参数,那它就不是拷贝构造,而是普通构造函数

  3. 拷贝构造的第一个参数必须是该类对象的引用,不能是该类对象本身
    因为传值调用时,形参是实参的临时拷贝,所以规定了传对象本身的时候要调用拷贝构造函数
    这样的话,如果一个类的拷贝构造的参数是该类对象本身,那么调用拷贝构造,就要向传参,而传对象本身的时候又要调用拷贝构造,调用拷贝构造又要先传参数………
    就会无穷递归

    在这里插入图片描述

  4. 如果没有显式的写出拷贝构造函数,编译器会自动生成一个默认的拷贝构造函数
    这个默认的拷贝构造函数的特点是:
    1,对内置类型【int char等】成员直接浅拷贝
    2,对自定义类型【class,struct等】成员就调用该自定义类型自己的拷贝构造


浅拷贝和深拷贝

浅拷贝

把一个对象中的成员中存储的值直接拷贝给另一个对象的对应成员就是浅拷贝

下图就是一个浅拷贝的拷贝构造函数
在这里插入图片描述
浅拷贝的缺点:
如果对象的成员申请了资源,那么成员中存储的往往是那片资源的地址

此时如果使用浅拷贝,就直接把这个成员中存储的地址给了另一个对象的成员,那么这两个对象的成员就会指向同一片资源,这样不仅使用不方便,析构释放资源的时候还会多次释放,导致程序崩溃


在这里插入图片描述
上图相当于
在这里插入图片描述

解决办法也很简单,就让两个对象指向的资源不是同一片就可以了,也就是深拷贝


深拷贝

当对象有成员指向资源的时候,如果要把这个对象拷贝给其他对象就要用深拷贝

深拷贝很简单,分2步

  1. 先“拷贝”指向资源的数据结构
    即如果成语指向的资源是一条节点都在堆区的链表,这个时候接受拷贝的对象的成员就也要在堆区申请空间,创建节点,制造出于那条链表相同的节点个数和节点大小

  2. 再拷贝数据
    即把指向资源中存储的有效数据拷贝个另一个成员

例 上面例举的浅拷贝时的问题就可以这样解决
在这里插入图片描述


拷贝构造函数的调用场景

  1. 使用已经创建好的对象去创建新的对象
    在这里插入图片描述

  2. 函数的参数类型是类的对象
    因为形参是实参的临时拷贝,所以当参数是类的对象的时候,就要创建一个对象作为形参,当调用该函数的时候,编译器自动调用拷贝构造

    在这里插入图片描述

3.函数的返回值是类的对象
因为在函数调用结束后函数的栈区内存会被回收,如果返回的是在函数内创建的对象,函数调用结束后,这个对象的生命周期也会结束,空间会被释放
为了防止这样的情况,就需要创建一个临时对象来存储可能被销毁的对象的数据,这个临时对象就要编译器自动调用拷贝构造函数创建


http://www.mrgr.cn/p/38327224

相关文章

js逆向实战之中国男子篮球职业联赛官方网站返回数据解密

url:https://www.cbaleague.com/data/#/teamMain?teamId=29124 分析过程看流量包,返回数据全是加密的字符串,要做的就是解密回显数据。由于这里的网址都比较特殊,里面都带有id号,所以通过url关键字去搜索不是一个很好的办法。看initiators,里面有很多异步传输。异步传输…

Linux应急响应小结

通过系统运行状态、安全设备告警,主机异常现象来发现可疑现象通常的可疑现象有:资源占用、异常登录、异常文件、异常连接、异常进程等。目录用户排查历史命令网络排查进程排查文件排查持久化排查日志分析 通过系统运行状态、安全设备告警,主机异常现象来发现可疑现象通常的可…

XSS漏洞靶场

XSS漏洞靶场 level1 查看网站源码,发现get传参name的值test插入到了html头里面,还回显payload长度插入js代码,get传参 ?name=<script>alert()</script>本关小结:JS弹窗函数alert() level2貌似不对,查看下源码闭合掉双引号 "> <script>alert()&…

Laravel 6 - 第十一章 中间件

​ 文章目录 Laravel 6 - 第一章 简介 Laravel 6 - 第二章 项目搭建 Laravel 6 - 第三章 文件夹结构 Laravel 6 - 第四章 生命周期 Laravel 6 - 第五章 控制反转和依赖注入 Laravel 6 - 第六章 服务容器 Laravel 6 - 第七章 服务提供者 Laravel 6 - 第八章 门面 Laravel 6 - …

(2022级)成都工业学院数据库原理及应用实验六: SQL DML(增、删、改)

写在前面 1、基于2022级软件工程/计算机科学与技术实验指导书 2、成品仅提供参考 3、如果成品不满足你的要求&#xff0c;请寻求其他的途径 运行环境 window11家庭版 Navicat Premium 16 Mysql 8.0.36 实验要求 在实验三的基础上完成下列查询&#xff1a; 1、在科室表…

WIFI加密方式对无线速率的影响

目录无线加密三种选择:WEP、WPA和WPA2测试平台和测试方法非加密和WEP加密测试 结果差别巨大非加密条件下 300M无线路由实测WEP加密条件下 300M无线路由实测TKIP加密算法:WPA与WPA2成绩低迷WPA加密(TKIP加密算法)条件下 300M无线路由实测WPA2加密(TKIP加密算法)条件下 300…

10.Godot Input与自定义单例的使用

单例 单例是一个可以在任何一个脚本中对其进行直接访问的对象&#xff0c;分为内置单例与自定义单例。每个单例都是独一无二的对象。内置单例不是节点&#xff0c;主要成员是各类 Server&#xff0c;开发者可以使用它们直接控制游戏程序的图形与音效等内容。此外&#xff0c;还…

偶然看到一个古老的算法

九韶精选,你值得拥有只能说秦哥牛批!!!那个破三角公式到现在还没记住c++代码实现 #include<bits/stdc++.h> using namespace std; int n; int main(){cin>>n;//输入多项式的次数double *a=new double[n+1];//n次多项式申请n+1大小的数组for(int i=n;i>=0;i--)//…

JVM 内存溢出、泄漏与引用

1、引用概述在栈上的reference类型存储的数据代表某块内存地址,称reference为某内存、某对象的引用。实际上引用分为很多种,从强到弱分为:强引用 > 软引用 > 弱引用 > 虚引用。平常我们使用的引用实际上是强引用,各种引用有自己的特点,强引用就是Java中普通的对象…

解决VSCode中“#include错误,请更新includePath“问题

目录 1、问题原因 2、解决办法 1、问题原因 在编写C程序时&#xff0c;想引用头文件但是出现如下提示&#xff1a; &#xff08;1&#xff09;首先检查要引用的头文件是否存在&#xff0c;位于哪里。 &#xff08;2&#xff09;如果头文件存在&#xff0c;在编译时提醒VSCo…

CMakeLists.txt中如何添加编译选项?

1. 引子 编译器有多种可供选择&#xff0c;如g、c、clang等&#xff0c;如下以c作为示例。 2. 使用CMAKE_CXX_FLAGS添加编译选项 在Makefile中可能用类似如下的指令来添加编译选项&#xff1a; /usr/bin/c -Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unuse…

深入理解Python协程:从基础到实战

title: 深入理解Python协程:从基础到实战 date: 2024/4/27 16:48:43 updated: 2024/4/27 16:48:43 categories:后端开发tags:协程 异步IO 并发编程 Python aiohttp asyncio 网络爬虫第1章:协程基础 1.1 协程概念介绍 协程(Coroutines)是一种特殊的软件构造,它允许程序在执…

leetCode60. 排列序列

leetCode60. 排列序列 方法一:语法版&#xff0c;面试官不认可的方法&#xff1a;next_permutation函数 // 方法一&#xff1a;使用next_permutation函数&#xff0c;将某容器设置为当前按照字典序 // 的下一个全排列的内容 class Solution { public:string getPermutation(in…

四数之和 ---- 双指针

题目链接 题目: 分析: 我们已经知道三数之和如何求取, 并去重了 三数之和 那么四数之和同理, 需要固定两个数a和b 然后用"双指针算法" , 只要两指针之和等于target-a-b即可同样对于四个数都要进行去重 代码: class Solution {public List<List<Integer>…

Vue入门到关门之前端引入

一、前端发展历史 1、什么是前端&#xff1f; 前端&#xff1a;针对浏览器的开发&#xff0c;代码在浏览器运行后端&#xff1a;针对服务器的开发&#xff0c;代码在服务器运行 2、前后端不分的时代 互联网发展的早期&#xff0c;前后端开发是一体的&#xff0c;前端代码是…

Git 使用教程(新手学习)

Git 是一种分布式版本控制系统,用于管理软件项目的源代码。它是由 Linux 之父 Linus Torvalds 开发的,并已经成为了现代软件开发领域中最流行的版本控制系统之一。 使用 Git 可以追踪代码的历史修改记录,方便团队协作、代码共享和代码重构。Git 的基本工作流程如下: 在开始…

jwt的思路

我们通常在项目中使用登录接口的时候,会利用jwt的token实现一个对其他接口的一个请求头这层的一个验证,那么如何去应用呢,正常来讲我们需要写出两个功能 1.jwt基本的加密和解密 2.jwt的一个拦截器,检验token请求头使用依赖 jdk1.8仅需<dependency><groupId>io.json…

一道编程题引发的C中关于数组、指针的思考

7-163 谷歌的招聘由一道编程题引发的C中关于数组、指针的思考先来看三种数组定义方式 #include <stdio.h> #include <stdlib.h>int main(){//方式1int array_1[4] = {1};//方式2,变长数组int n2;scanf("%d",&n2);int array_2[n2]; //使用变长数组pri…

【003_音频开发_基础篇_Linux进程通信(20种你了解几种?)】

003_音频开发_基础篇_Linux进程通信&#xff08;20种你了解几种&#xff1f;) 文章目录 003_音频开发_基础篇_Linux进程通信&#xff08;20种你了解几种&#xff1f;)创作背景Linux 进程通信类型fork() 函数fork() 输出 2 次fork() 输出 8 次fork() 返回值fork() 创建子进程 方…

力扣-498. 对角线遍历

1.题目 题目地址(498. 对角线遍历 - 力扣(LeetCode)) https://leetcode.cn/problems/diagonal-traverse/ 题目描述 给你一个大小为 m x n 的矩阵 mat ,请以对角线遍历的顺序,用一个数组返回这个矩阵中的所有元素。示例 1:输入:mat = [[1,2,3],[4,5,6],[7,8,9]] 输出:[1,…