网站手机适配跳转/国际新闻最新消息今天军事新闻
系列文章目录
http://t.csdnimg.cn/d0MZH
目录
- 系列文章目录
- http://t.csdnimg.cn/d0MZH
- 比喻和理解
- a.比喻
- C语言开空间
- C++开空间
- b.理解
- a、C语言的内存管理的缺点
- 1、开发效率低(信息传递繁琐)
- 2、可读性低(信息展示混乱)
- 3、稳定性差(开空间可能失败)
- 代码演示
- b、C++的内存管理方式的优点
- 1、开发效率高、稳定
- 2、可读性高(信息集中、整洁)
- 一、C++又提出了自己的内存管理方式——通过new和delete操作符进行动态内存管理
- 1. 我们在建开辟空间时会发现我们有4个核心需求:
- 2. C++将开辟和释放分别集中在new和delete两个操作符实现:
- 3. new集成:malloc、抛异常、构造函数;delete集成free、抛异常、析构函数
- 4.new和delete内含的功能会根据具体的情况选择性发挥作用
- 二、 operator new与operator delete函数
- 1、 operator new与operator delete函数
- 三、内置类型
- 四、自定义类型
- 1、new的原理
- 2、delete的原理
- 3、new T[N]的原理
- 4、delete[ ]的原理
- delete[ ]底层原理
比喻和理解
C语言无法方便进行内存管理,C语言有关空间的所有操作都充满了冗余操作;
而C++通过new和delete操作符进行动态内存管理。
简而言之,C++对内存管理的创举主要是让我们输入的信息更高效的被编译器理解。
a.比喻
C语言开空间
打个比方,C语言开辟空间就像是:你要开席,你叫C语言去买10瓶可乐,C语言会做下面这些事:
问无效信息;
它一次只买一瓶,重复十次买一瓶的操作,它每买一瓶都问你去哪家店买、走哪条路;不会思考;
买可乐的预算有多少,购买策略要你全部说清楚,购买时遇到意料之外的情况就打电话问你;轻易放弃,结果不上报;
如果C语言在去的第一家商店购买失败,它就不买了,也不会主动报告购买失败,需要我们专门询问,要是不问C语言就放任错误发生;
C++开空间
而C++就像是:你叫C++去买10瓶可乐,它会问你一些信息,然后再做以下事情:
主动思考
C++会问你给它多少预算,给多少人喝,每人喝几杯,购买现场它根据这些信息自己决定购买策略。灵活多变
如C++在商店购买失败,它会自动换一家商店买。有责任感
换商店会一直换到成功为止,除非彻底买不到才打电话上报。
b.理解
a、C语言的内存管理的缺点
1、开发效率低(信息传递繁琐)
- 内存空间开辟需要显示定义
- 内存空间开辟代码编写繁琐
2、可读性低(信息展示混乱)
- 代码修改检查要反复对比
- 代码开空间显示不整齐
3、稳定性差(开空间可能失败)
- 就算声明了开空间,也不确定有没有开空间
- 开空间失败不自动报警,需要我们设置报警
代码演示
如下代码,我们的计划实现:
- 开一块空间存 int 类型的数据;
- 开辟这块空间并且初始化;
- 在原空间的基础上扩容;
为了实现以上功能,我们要写大量和我们的意图没有任何关系的内容。
代码演示:用C语言的方法开辟空间,可以看到这些代码是非常冗余的:
void Test()
{int* p1 = (int*)malloc(sizeof(int)); //开辟一个int大小的空间int* p2 = (int*)calloc(4, sizeof(int)); //开4个int大小的空间并且初始化为0int* p3 = (int*)realloc(p2, sizeof(int) * 10); //扩容,把大小扩大到10个int,并且转移空间地址到p31
}
糟糕的是上面三行代码如果开空间失败不会自动报警
b、C++的内存管理方式的优点
在实践时可以发现,我们编码时思维聚焦于开辟空间的用途;
同时也发现,实现功能时会反复使用同样的空间大小和变量类型。
1、开发效率高、稳定
如下代码,我们要修改开辟的空间属性,只需要在开空间的代码上微调即可;
void Test()
{// 动态申请一个int类型的空间int* ptr4 = new int;// 动态申请一个int类型的空间并初始化为10int* ptr5 = new int(10);// 动态申请5个int类型的空间,并初始化为0int* ptr6 = new int[5];// 动态申请5个int类型的空间并初始化前3个空间,后面2个空间默认为0int* ptr7 = new int[5]={1,2,3};delete ptr4;delete ptr5;delete[] ptr6;delete[] ptr7;
}
简而言之,开辟一个空间,进行一番操作初始化它,就是我们的常做的操作;
由此,通过自定义类型就可以实现:通过一个类我们可以在开辟一个空间的同时启动一个构造函数对这个空间进行操作;
如下代码:
我们定义了一个自定义类型A,当我们使用new来开辟空间时,会自动启动A的构造函数;
#include<iostream>
using namespace std;
static int i = 1;class A
{
public:A(int a = 0): _a(a){cout << "A(" << i++ << "):" << this << endl;}~A(){cout << "~A():" << this << endl;}
private:int _a;
};int main()
{// new/delete 和 malloc/free最大区别是 // new/delete对于【自定义类型】除了开空间,还会调用构造函数和析构函数A* p4 = new A(1); // 开辟一个int空间A* p5 = new A[10]{1,2,3,4,5};A* p6 = new A[10];delete p4;delete[] p5;delete[] p6;return 0;
}
2、可读性高(信息集中、整洁)
一、C++又提出了自己的内存管理方式——通过new和delete操作符进行动态内存管理
1. 我们在建开辟空间时会发现我们有4个核心需求:
开辟空间(1、2),释放空间(3、4):
- 开辟空间;
- 初始化空间;
- 释放空间;
- 指针置空
2. C++将开辟和释放分别集中在new和delete两个操作符实现:
new实现:
1.开辟空间、2.初始化空间;
delete实现:
3.释放空间、4.指针置空;
在申请自定义类型的空间时,new会自动调用operator new和构造函数,delete会自动调用operator delete 和 析构函数。
3. new集成:malloc、抛异常、构造函数;delete集成free、抛异常、析构函数
- new 是operator new 和构造函数的结合, delete 是oprator delete 和析构函数的结合;
- perator new 是malloc和抛异常的结合,oprator delete 是free和抛异常的结合。
4.new和delete内含的功能会根据具体的情况选择性发挥作用
- 在new 起作用的过程中,固定发挥malloc、抛异常、构造函数初始化空间;
- 在delete 起作用的过程中,固定发挥free、抛异常的作用,根据情况来判断是否调用析构函数 释放空间;
如果开空间时没有malloc开辟空间,则当我们要释放空间时,我们可以去使用free或delete释放空间,因为此时delete只有free可以发挥作用,没有调用析构函数的必要;
如下代码:对p1象占用了int类型的空间,我们使用free就可以释放这个空间;
相同情况下,p2使用delete也是可以的;
同理,p3的int【10】也是free、delete皆可。
#include<iostream>
using namespace std;class A
{
public:A(int a = 0):_a(a){cout << a << "构造" << endl;}private:int _a;
};int main()
{// new和delete内含的功能会根据具体的情况选择性发挥作用A* p1 = new A(1); //这里p1使用了int空间,我们delete或free释放即可A* p2 = new A(1); //这里p2使用了int空间,我们delete或free释放即可free(p1);delete p2;A* p3 = new A[10];delete[] p3;return 0;
}
二、 operator new与operator delete函数
1、 operator new与operator delete函数
new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。
operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败,尝试执行空间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。
如下代码我们尝试通过new来创建一个对象
#include<iostream>
using namespace std;typedef char DataType;
class Stack
{
public:Stack(size_t capacity = 4){cout << "Stack()" << endl;_array = new DataType[capacity];_capacity = capacity;_size = 0;}void Push(DataType data){// CheckCapacity();_array[_size] = data;_size++;}~Stack(){cout << "~Stack()" << endl;_array = nullptr;_size = 0;_capacity = 0;}private:// 内置类型DataType* _array;int _capacity;int _size;
};Stack* func(){int n;cin >> n;Stack* pst = new Stack(n);return pst;
}int main()
{Stack* ptr = func();ptr->Push(1);ptr->Push(2);delete ptr;return 0;
}
三、内置类型
如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:
- new/delete申请和释放的是单个元素的空间;
- new[ ]和delete[ ]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。
四、自定义类型
1、new的原理
- 调用operator new函数申请空间
- 在申请的空间上执行构造函数,完成对象的构造
A* p1 = new A(1);
2、delete的原理
- 在空间上执行析构函数,完成对象中资源的清理工作
- 调用operator delete函数释放对象的空间
delete p1;
3、new T[N]的原理
- 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请
- 在申请的空间上执行N次构造函数
- 返回开辟空间的地址
A* p2 = new A[10];
4、delete[ ]的原理
- 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
- 调用operator delete[]释放空间,实际在operator delete[]中调用数个operator delete来释放空间
delete[] p2;
delete[ ]底层原理
delete[]被设计用来释放多个连续的同构造空间,那么它需要获取两个信息:
- 被释放空间的位置——在delete[]后接的地址p2;
- 调用几次析构函数——在我们使用new[]的时候,会自动在存储信息的空间前面开一个空间用来记录该空间存储了多少个对象。
如下代码:
A* p2 = new A[10];delete[] p2;
我们使用了new A[10]开辟了十个存储int数据的空间,我们的指针p2也指向了这个空间的第一个元素的地址;
而当我们调用delete[]来释放该空间时,delete[ ]空着的[ ]就会把p2前面四个字节的内容作为整形装到[]里面,于是在编译器看来 delete[] p2 就变成了 “ delete[10] p2” ;
由此编译器知道了需要调用十次析构函数释放该空间,同时p2也被修改指向了该空间真正的起始地址,最后释放空间时会把开头的4个字节和后面的40个字节一起释放掉,然后p2被置空。至此new A[10]所占用的空间被全部释放;
相关文章:

C++学习笔记—— C++内存管理方式:new和delete操作符进行动态内存管理
系列文章目录 http://t.csdnimg.cn/d0MZH 目录 系列文章目录http://t.csdnimg.cn/d0MZH 比喻和理解a.比喻C语言开空间C开空间 b.理解a、C语言的内存管理的缺点1、开发效率低(信息传递繁琐)2、可读性低(信息展示混乱)3、稳定性差&…...

8、操作符重载
友元 可以通过friend关键字,把一个全局函数、另一个类的成员函数或者另一个类整体,声明为授权类的友元友元拥有访问授权类任何非公有成员的特权友元声明可以出现在授权类的公有、私有或者保护等任何区域且不受访问控制限定符的约束友元不是成员…...

前端组件库开发
通常我们会使用很多组件库,有时候我们会去看源码比如element,antd,然后发现多少是按需导出,和vue.use全局注册,依赖于框架的拓展。 组件库的开发依赖框架的版本和node的版本,这个是需要说明的,然…...

自定义日志打印功能--C++
一、介绍 日志是计算机程序中用于记录运行时事件和状态的重要工具。通过记录关键信息和错误情况,日志可以帮助程序开发人员和维护人员追踪程序的执行过程,排查问题和改进性能。 在软件开发中,日志通常记录如下类型的信息: 事件信…...

gitlab注册无中国区电话验证问题
众所周知gitlab对中国区不友好,无法直接注册,页面无法选择86的手机号进行验证码发送。 Google上众多的方案是修改dom,而且时间大约是21年以前。 修改dom,对于现在的VUE、React框架来说是没有用的,所以不用尝试。 直接看…...

【JAVA基础题目练习】----第二天
JAVA基础题目练习 1. 键盘录入数据,比较大小2. 代码重构(简化代码,少做判断)3. 键盘录入月份的值,输出对应的季节4. 获取三个数据中的最大值使用IF语句5. 用switch语句实现键盘录入月份,输出对应的季节6. 求…...

node.js和npm的安装与环境配置(2023最新版)
目录 安装node.js测试是否安装成功测试npm环境配置更改环境变量新建系统变量 安装node.js 1、进入官网下载:node.js官网 我选择的是windows64位的,你可以根据自己的实际情况选择对应的版本。 2、下载完成,安装。 打开安装程序 接受协议 选…...

ke14--10章-1数据库JDBC介绍
注册数据库(两种方式),获取连接,通过Connection对象获取Statement对象,使用Statement执行SQL语句。操作ResultSet结果集 ,回收数据库资源. 需要语句: 1Class.forName("DriverName");2Connection conn DriverManager.getConnection(String url, String user, String…...

【IC验证】perl脚本——分析前/后仿用例回归情况
目录 1 脚本名称 2 脚本使用说明 3 nocare_list文件示例 4 脚本执行方法 5 postsim_result.log文件示例 6 脚本代码 1 脚本名称 post_analysis 2 脚本使用说明 help:打印脚本说明信息 命令:post_analysis help 前/后仿结束后,首先填…...

Ansible适合的场景是什么?
Ansible将编排与配置管理、供应和应用程序部署结合并统一在一个易于使用的平台上。Ansible的一些主要场景包括: 配置管理:集中配置文件管理和部署是Ansible的一个常见场景。 应用程序部署:当使用Ansible定义应用程序,并使用Ansible Tower管…...

Flink 读写 HBase 总结
前言 总结 Flink 读写 HBase 版本 Flink 1.15.4HBase 2.0.2Hudi 0.13.0官方文档 https://nightlies.apache.org/flink/flink-docs-release-1.17/zh/docs/connectors/table/hbase/ Jar包 https://repo1.maven.org/maven2/org/apache/flink/flink-sql-connector-hbase-2.2/1…...

记录一次chatGPT人机协同实战辅助科研——根据词库自动进行情感分析
有一个Excel中的一列,读取文本判断文本包含积极情感词.txt和消极情感词.txt的个数,分别生成两列统计数据 请将 ‘your_file.xlsx’ 替换为你的Excel文件名,Your Text Column’替换为包含文本的列名。 这个程序首先读取了积极和消极情感词&…...

Java_LinkedList链表详解
目录 前言 ArrayList的缺陷 链表 链表的概念及结构 链表的种类 1.单向或双向 2.带头或不带头 3.循环或不循环 LinkedList的使用 什么是LinkedList LinkedList的使用 LinkedList的构造 LinkedList的其他常用方法介绍 LinkedList的遍历 ArrayList和LinkedList的…...

MacOS 12 开放指定端口 指定ip访问
MacOS 12 开放指定端口 指定ip访问 在 macOS 上开放一个端口,并指定只能特定的 IP 访问,你可以使用 macOS 内置的 pfctl(Packet Filter)工具来实现。 以下是一些基本的步骤: 1、 编辑 pf 配置文件: 打开 /…...

LeedCode刷题---滑动窗口问题
顾得泉:个人主页 个人专栏:《Linux操作系统》 《C/C》 《LeedCode刷题》 键盘敲烂,年薪百万! 一、长度最小的子数组 题目链接:长度最小的子数组 题目描述 给定一个含有 n 个正整数的数组和一个正整数 target 。…...

leetcode24. 两两交换链表中的节点
题目描述 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。 示例 1: 输入:head [1,2,3,4] 输出&#…...

TCP传输层详解(计算机网络复习)
介绍:TCP/IP包含了一系列的协议,也叫TCP/IP协议族,简称TCP/IP。该协议族提供了点对点的连接机制,并将传输数据帧的封装、寻址、传输、路由以及接收方式都予以标准化 TCP/IP的分层模型 在讲TCP/IP协议之前,首先介绍一…...

【LuatOS】简单案例网页点灯
材料 硬件:合宙ESP32C3简约版,BH1750光照度模块,0.96寸OLED(4P_IIC),杜邦线若干 接线: ESP32C3.GND — OLED.GND — BH1750.GND ESP32C3.3.3V — OLED.VCC — BH1750.VCC ESP32C3.GPIO5 — OLED.SCL — BH1750.SCL E…...

百度APP iOS端包体积50M优化实践(七)编译器优化
一. 前言 百度APP iOS端包体积优化系列文章的前六篇重点介绍了包体积优化整体方案、图片优化、资源优化、代码优化、无用类优化、HEIC图片优化实践和无用方法清理,图片优化是从无用图片、Asset Catalog和HEIC格式三个角度做深度优化;资源优化包括大资源…...

STM32-新建工程(标准库)
目录 STM32F10x新建工程(标准库) 移植文件夹 新建工程 添加启动文件和必需文件 在工程中加载新添加的文件 在工程中添加文件路径 在工程中添加main函数 添加lib库 添加必需文件 添加宏定义 点亮LED(标准库) STM32F10x新…...

Android集成科大讯飞语音识别与语音唤醒简易封装
目录 一、语音唤醒部分 1、首先在科大讯飞官网注册开发者账号 2、配置唤醒词然后下载sdk 3、选择对应功能下载 4、语音唤醒lib包全部复制到工程目录下 5、把语音唤醒词文件复制到工程的assets目录 6、复制对应权限到AndroidManifest.xml中 7、唤醒工具类封装 二、语音识…...

【Linux】telnet命令使用
telnet命令 telnet命令用于使用telnet协议与另一台主机进行通信。如果在没有主机参数的情况下调用telnet,它将进入命令模式,由其提示(telnet>)指示。在这种模式下,它接受并执行下面列出的命令。如果使用参数调用它…...

VCG 标记使用(BitFlags)
文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 对于网格的每个单形,我们都有一个称为BitFlags的组件,该组件存储固定大小的32位向量,用于各种需求。管理这些标志的相关类:vcg::tri::UpdateFlags与vcg::tri::UpdateSelection。主要的标记有:删除标记、边界标记…...

Pandas中的Series(第1讲)
Pandas中的Series(第1讲) 🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔…...

从手工测试进阶中高级测试?如何突破职业瓶颈...
目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 1、手工测试如何进…...

【链表Linked List】力扣-114 二叉树展开为链表
目录 题目描述 解题过程 官方题解 题目描述 给你二叉树的根结点 root ,请你将它展开为一个单链表: 展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。展开后的单链表应…...

Go (一) 基础部分4 -- 文件处理
一、文件基本介绍 1.1、打开一个文件 基本介绍:打开一个文件用于读取,如果操作成功,返回的文件对象的方法可用于读取文件数据。如果出错,错误底层类型是"*.PathError" func Open(name string) (*File, error) name stri…...

集合03 Collection (List) - Java
List ArrayListArrayList注意事项ArrayList底层操作机制-源码分析(重点) VectorVector基本介绍 ——Vector和ArrayList比较Vector底层结构和源码分析 LinkedList基本介绍LinkedList的底层结构和操作机制LinkedList的增删改查 ——LinkedList和ArrayList比…...

国产化软件突围!怿星科技eStation产品荣获2023铃轩奖“前瞻优秀奖”
11月11日,2023中国汽车供应链峰会暨第八届铃轩奖颁奖典礼在江苏省昆山市举行。怿星科技凭借eStation产品,荣获2023铃轩奖“前瞻智能座舱类优秀奖”,怿星CEO潘凯受邀出席铃轩奖晚会并代表领奖。 2023铃轩奖“前瞻智能座舱类优秀奖” 铃轩奖&a…...

如何解决Redis热Key问题?
Redis热点key是指访问频率较高的key,当大量的请求集中在一个或少数几个热点key上时,会导致这些key所在的Redis节点的CPU、内存和网络带宽等资源被大量消耗,影响Redis集群的整体性能和稳定性。 热点Key带来的问题 Redis节点负载过高࿱…...