Cpp05 — 内存管理

news2025/2/25 0:30:16

内存管理

代码是以文件的形式存储在磁盘上的。

不是说是代码就会加载到代码段,而是代码编译好的二进制指令代码会加载到代码段,然后程序中main函数执行时就是在代码段取指令来执行。栈和堆上的数据是运行时才建立的。

常量区是有硬件保护的,只要去访问,就会报错

new、delete、malloc、free

new、malloc

new是一个操作符,malloc是函数

int* p1 = new int;//申请1个int

int* p2 = new int[5];//申请有5个int元素的数组

int* p3 = new int(5);//申请1个int对象,初始化为5

new不会初始化,除非有指定。

C++98不支持new时初始化数组,C++11支持

int* p4 = new int[5]{1,2,3,4,5};

A* p3 = new A[2]{A(1), A(2)};

注意:数量要匹配,不会帮补0的

delete、free

delete p1;

delete []p2;//释放多个空间,[]中不用写东西

new和delete数量要匹配,不匹配有时候会报警告。

关键字、操作符:new、delete   函数:malloc、free

对于内置类型:new\delete与malloc\free没有本质区别,只是new和delete用法简化了一点。

对于自定义类型:有很大的区别。new对于自定义类型不仅会开空间,还会去调用它的构造函数去初始化,而malloc没有。(delete会调用其析构函数然后释放空间)

区别:

1.new在申请空间时还会调用其构造函数初始化,不提供默认构造函数的话会报错,即使没有,也可以传参,传了就没错了。

2.delete调用析构函数清理对象中的资源,然后释放空间

结论:new/delete是为内置类型准备的,不仅在堆上申请出来,还会调用构造和析构清理

3.malloc失败是返回NULL,一般不会失败,除非开的空间太大了,或者内存不够了,cout打印char*时,打印出来的不是地址,而是字符串,int*那些的不会出现这样的问题,因为会觉得它是指针。而new失败是抛异常,new失败不需要检查返回值,因为它失败是抛异常,异常是面向对象语言处理错误的一种方式,与继承和多态有关

因为申请的是虚拟内存,所以与电脑配置无关,虚拟内存的大小都是4G

free之后,数据还在,只是我们没有它的访问权限了,没有对它直接使用的权限了。

先定义的先构造、后析构

底层原理

其实new的底层是调用了两个函数,即调用operator new去堆上开空间,调用构造函数去初始化,这里的operator new不是对new的重载,而是一个全局函数,其底层是调用malloc开空间。

operator new存在的意义:封装malloc,帮助new开空间,为什么不直接调malloc呢?这样处理符合C++new的失败机制(失败抛异常)。

(其实operator new就可以了,只是为了成一对才有operator delete)

operator new我们也可以直接使用,其实和new是一样的

重载operator new和operator delete,比如我们想检测内存泄漏,重载一下就可以

::域作用限定符,如果没写的话还是调的是库里的,调用的时候可以这么调,建议是对new和delete进行宏替换,这样就会调到它们

原理:

/*
operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败,尝试执行空间不足。应对措施,如果应对措施用户设置了,则继续申请,否则抛异常。
*/

/*
operator delete: 该函数最终是通过free来释放空间的 
*/

/*
free的实现 
*/
#define   free(p)               _free_dbg(p, _NORMAL_BLOCK)

通过上述两个全局函数的实现知道,operator new 实际也是通过malloc来申请空间,如果 
malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。operator delete 最终是通过free来释放空间的。

重载:

// 重载operator delete,在申请空间时:打印在哪个文件、哪个函数、第多少行,申请了多少个 
字节
void* operator new(size_t size, const char* fileName, const char* funcName, 
size_t lineNo)
{
void* p = ::operator new(size);
cout << fileName << "-" << funcName << "-" << lineNo << "-" << p << "-" 
<< size << endl;
return p; 
}
// 重载operator delete,在释放空间时:打印再那个文件、哪个函数、第多少行释放
void operator delete(void* p, const char* fileName, const char* funcName, 
size_t lineNo)
{
cout << fileName << "-" << funcName << "-" << lineNo << "-" << p << 
endl;
    ::operator delete(p); 
}
int main() 
{
// 对重载的operator new 和 operator delete进行调用
int* p = new(__FILE__, __FUNCTION__, __LINE__) int; 
operator delete(p, __FILE__, __FUNCTION__, __LINE__); 
return 0;
}
// 上述调用显然太麻烦了,可以使用宏对调用进行简化
// 只有在Debug方式下,才调用用户重载的 operator new 和 operator delete
#ifdef _DEBUG
#define new new(__FILE__, __FUNCTION__, __LINE__)
#define delete(p) operator delete(p, __FILE__, __FUNCTION__, __LINE__) 
#endif
int main() 
{
int* p = new int; 
delete(p); 
return 0;
}

重载一个类专属的operator new

当一个结点需要被频繁开辟,需要频繁申请,效率就比较低,语言里面有一个池化技术,我们可以申请一个内存池。C++的库里有一个内存池:allocator第十节3:20:00到完

malloc/free和new/delete的区别

malloc/free和new/delete的共同点是:都是从堆上申请空间,并且需要用户手动释放。不同的地 
方是:
1. malloc和free是函数,new和delete是操作符
2. malloc申请的空间不会初始化,new可以初始化
3. malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可, 
如果是多个对象,[]中指定对象个数即可
4. malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型
5. malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需 
要捕获异常
6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new 
在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成 
空间中资源的清理

语法使用的区别、本质功能的区别

 

第十节 3:20:00

 

定位new表达式

定位new是在已有内存空间中调用构造函数初始化一个对象。即创建空间后,想对已创建的对象进行初始化时使用。

使用格式:new(place_address)type或new(place_address)type(initializer_list)

 ​​​​​

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JAVA】java中的逻辑控制

作者主页&#xff1a;paper jie的博客 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文录入于《JAVASE语法系列》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白精心打造的。笔者用重金(时间和精…

Android应用开发(22)获取Property系统属性

Android应用开发学习笔记——目录索引 开发过程中我们经常需要获取Property系统属性&#xff0c;比如model、device、product 等等&#xff0c;通常debug的时候可以使用如下命令获取。 adb shell getprop <property name> adb shell setprop <property name> <…

Unity 四元素

//-------------旋转------------ // //设置角度 (超过90或负数时&#xff0c;会设置-1结果是359这样的问题&#xff0c;可以使用下面旋转的方式) transform.rotate new Quaternion(0,0,0,0);//Quaternion四元数 transform.localEulerAngles new Vector3(0,0,0);//EulerA…

idea集成jrebel实现热部署

文章目录 idea集成jrebel实现热部署下载jrebel 插件包下载jrebel mybatisplus extensition 插件包基础配置信息情况一其次情况三情况四情况五情况六情况七 验证生效与否 Jrebel热部署不生效的解决办法 idea集成jrebel实现热部署 在平常开发项目中&#xff0c;我们通常是修改完…

Android应用开发(23)获取亮灭屏状态

Android应用开发学习笔记——目录索引 在android 应用程序获取亮灭屏状态的常用方法有&#xff1a; 使用PowerManager提供的API函数注册Broadcast监听 一、使用PowerManager提供的API函数 frameworks/base/core/java/android/os/PowerManager.java import android.os.Buil…

Java 模块化Modularity- 了解与测试

1. java9后JDK后目录的变化 不见了jre,新增了jmods目录。 1&#xff09;为什么不见了jre&#xff1f; 新版JDK提供了 jlink工具&#xff0c;使用它构建一个包含jre镜像的应用程序。 就是可以打包一个引用程序内部已经包含完整或部分jre&#xff0c;可以直接运行。 2&#xf…

2023 7-30

题目1 lee2331.计算布尔二叉树的值 对于一棵完整的二叉树(每一个根节点孩子的个数不是0就是2) 叶子节点是1或者是0,其中1代表true,0代表false非叶子节点的值是2或者3,其中2代表逻辑或or,3代表逻辑与and计算方式 如果节点是个叶子节点,那么节点的 值 为它本身,即 True 或者…

1400*D. Pair of Topics

Examples input 5 4 8 2 6 2 4 5 4 1 3 output 7 input 4 1 3 2 4 1 3 2 4 output 0 题意&#xff1a; 选择两列&#xff0c;使得上面两个值的和比下面两个值之和大。 解析&#xff1a; 令c[ i ] a[ i ] - b[ i ]&#xff0c;转换成选两个值&#xff0c;其和大于0 排…

《MySQL 实战 45 讲》课程学习笔记(二)

日志系统&#xff1a;一条 SQL 更新语句是如何执行的&#xff1f; 与查询流程不一样的是&#xff0c;更新流程还涉及两个重要的日志模块&#xff1a;redo log&#xff08;重做日志&#xff09;和 binlog&#xff08;归档日志&#xff09;。 重要的日志模块&#xff1a;redo l…

【图论】差分约束

一.情景导入 x1-x0<9 ; x2-x0<14 ; x3-x0<15 ; x2-x1<10 ; x3-x2<9; 求x3-x0的最大值&#xff1b; 二.数学解法 联立式子2和5&#xff0c;可得x3-x0<23;但式子3可得x3-x0<15。所以最大值为15&#xff1b; 三.图论 但式子多了我们就不好解了&#xff0…

深度学习实践——循环神经网络实践

系列实验 深度学习实践——卷积神经网络实践&#xff1a;裂缝识别 深度学习实践——循环神经网络实践 深度学习实践——模型部署优化实践 深度学习实践——模型推理优化练习 代码可见于&#xff1a; 深度学习实践——循环神经网络实践 0 概况1 架构实现1.1 RNN架构1.1.1 RNN架…

【Golang】Golang进阶系列教程--为什么说 Go 语言字符串是不可变的?

文章目录 前言推荐阅读 前言 最近有读者留言说&#xff0c;平时在写代码的过程中&#xff0c;是会对字符串进行修改的&#xff0c;但网上都说 Go 语言字符串是不可变的&#xff0c;这是为什么呢&#xff1f; 这个问题本身并不困难&#xff0c;但对于新手来说确实容易产生困惑…

一起学算法(选择排序篇)

距离上次更新已经很久了&#xff0c;以前都是非常认真的写笔记进行知识分享&#xff0c;但是带来的情况并不是很好&#xff0c;一度认为发博客是没有意义的&#xff0c;但是这几天想了很多&#xff0c;已经失去了当时写博客的初心了&#xff0c;但是我觉得应该做点有意义的事&a…

数学分析:流形的线性代数回顾

因为是线性的&#xff0c;所以可以把所有的系数都提取出去。这也是多重线性代数的性质。可以看成基本的各项自变量的乘法。 这里可以看到两个不同基向量下&#xff0c;他们的坐标转化关系。 引出了张量积&#xff0c;也就是前面提到的内容。 对偶空间的例子总是比较美好。 因为…

【暑期每日一练】 day9

目录 选择题 &#xff08;1&#xff09; 解析&#xff1a; &#xff08;2&#xff09; 解析&#xff1a; &#xff08;3&#xff09; 解析&#xff1a; &#xff08;4&#xff09; 解析&#xff1a; &#xff08;5&#xff09; 解析&#xff1a; 编程题 题一 …

小目标检测(1)——大恒(DaHeng)相机操作与控制编程

文章目录 引言正文相关开发库的介绍编程准备配置引用头文件GalaxyIncludes.h配置lib文件 具体编程过程初始化和反初始化枚举设备开关设备 属性控制属性控制器种类 图像采集控制和图像处理采单帧回调采集图像处理流对象属性控制 获取设备事件获取掉线事件通知 样例程序分析补充&…

6.3.tensorRT高级(1)-yolov5模型导出、编译到推理(无封装)

目录 前言1. YOLOv5导出2. YOLOv5推理3. 补充知识总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习 tensorRT 高级-yolov5模…

复习之linux高级存储管理

一、lvm----逻辑卷管理 1.lvm定义 LVM是 Logical Volume Manager&#xff08;逻辑卷管理&#xff09;的简写&#xff0c;它是Linux环境下对磁盘分区进行管理的一种机制。 逻辑卷管理器(LogicalVolumeManager)本质上是一个虚拟设备驱动&#xff0c;是在内核中块设备和物理设备…

内网隧道代理技术(十五)之 Earthworm的使用(二级代理)

Earthworm的使用(二级代理) 本文紧接着上一篇文章继续讲解Earthworm工具的使用 (二级代理)正向连接 二级正向代理发生在如下的情况: 1、Web服务器在公网,黑客可以直接访问 2、B机器在内网,黑客不能直接访问 3、Web服务器可以访问内网机器B 4、内网机器B可以访问公司…

jdk1.7与jdk1.8的HashMap区别1-基本结构与属性对比

一、数据结构差别 1.7&#xff1a;数组链表 1.8&#xff1a;数组链表红黑树 当链表的长度大于8时&#xff0c;数组长度大于64&#xff0c;原来的链表数据结构变为红黑树 二、HashMap中的关键属性和方法区别 方法/变量/类 JDK7 JDK8 备注 DEFAULT_INITIAL_CAPACITY 16 16…