【C++】C/C++内存管理-new、delete

文章目录

  • 一、C/C++内存分布
  • 二、C/C++中动态内存管理方式
    • 2.1 C语言中动态内存管理方式
    • 2.2 C++内存管理方式
  • 三、operator new和operator delete函数
    • 3.1 operator new和operator delete函数
    • 3.2 operator new与operator delete的类专属重载(了解)
  • 四、new和delete的实现原理
  • 五、定位new表达式(placement-new)(了解)
  • 六、面试题
  • 总结


ヾ(๑╹◡╹)ノ" 人总要为过去的懒惰而付出代价ヾ(๑╹◡╹)ノ"
在这里插入图片描述


一、C/C++内存分布

代码展示:

#include <iostream>
int a = 1;//a在静态区(数据段)
static int b = 1;//b在静态区(数据段)
int main()
{
	static int c = 1;//c在静态区(数据段)
	int d = 1;//d在栈区
	int num[10] = { 1, 2, 3 };//num在栈区
	const char c[] = "abcd";//c和*c在栈区;常量字符串的内容拷贝一份,赋值给数组c,所以这个字符串不是在常量区
	const char* p = "abcd";//p在栈区,在栈区创建一个变量p,来储存常量字符串的地址
	//*p在常量区:*p是p所指向的内容,常量字符串,
	int* p1 = (int*)malloc(sizeof(int) * 4);//p1在栈区,*p1是指针指向的地址,这个地址在堆区
	int* p2 = (int*)calloc(4, sizeof(int));
	int* p3 = (int*)realloc(p2, sizeof(int) * 4);
	free(p1);
	free(p2);
	return 0;
}

栈区 :局部变量
sizeof(数组名):整个数组的大小
sizeof(字符串):注意‘\0’

  1. 栈又叫堆栈–非静态局部变量/函数参数/返回值等等,栈是向下增长的。
  2. 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信。(了解)
  3. 堆用于程序运行时动态内存分配,堆是可以上增长的。
  4. 数据段-存储全局数据和静态数据。
  5. 代码段(常量区)-可执行的代码/只读常量。

二、C/C++中动态内存管理方式

2.1 C语言中动态内存管理方式

malloc/calloc/realloc/free
面试题:malloc/calloc/realloc的区别?

2.2 C++内存管理方式

C++通过new和delete操作符进行动态内存管理。【new动态开辟的空间不用检查是否开辟成功】

  • 对于内置类型,没有什么区别
  • 区别在自定义类型,C++自定义类型:【new】创建空间+调用构造函数初始化【delete】调用析构函数清理资源+释放空间【创建失败:抛异常】;C语言:【malloc】仅仅创建空间【free】仅仅释放空间【创建失败:返回空指针】
int main()
{
	int* p1 = new int;//new 1个对象
	int* p2 = new int[10];//new 10个对象
	int* p3 = new int(10);//new 1个对象,值初始化为10
	int* p4 = new int[6]{ 1, 2, 3, 4 };//new 6个对象,值初始化分别为1、2、3、4、0、0(C++11才支持)
	delete p1;//new出来的
	delete[] p2;//new[]出来的
	delete p3;//new出来的
	delete[] p4;//new[]出来的
	//注意要匹配,如果不匹配,不一定会报错。但是还是要匹配
	return 0;
}

注意:(1)申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[],注意:匹配起来使用。
(2)在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会。

三、operator new和operator delete函数

3.1 operator new和operator delete函数

  • new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。
  • operator new 实际也是通过malloc来申请空间,如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。operator delete 最终是通过free来释放空间的。

3.2 operator new与operator delete的类专属重载(了解)

  • 向堆申请空间,和向内存池申请空间比较,向内存池申请空间比较快。
  • 重载专属的operator new/ operator delete的函数,实现的函数,去向内存池申请空间。相当于向内存池申请空间比较快。使用内存池申请和释放内存,提高效率。

四、new和delete的实现原理

内置类型

如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。

自定义类型

  • new的原理
  1. 调用operator new函数申请空间
  2. 在申请的空间上执行构造函数,完成对象的构造
  • delete的原理
  1. 在空间上执行析构函数,完成对象中资源的清理工作
  2. 调用operator delete函数释放对象的空间
  • new T[N]的原理
  1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请
  2. 在申请的空间上执行N次构造函数
  • delete[]的原理
  1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
  2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间

五、定位new表达式(placement-new)(了解)

定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。
使用格式:
new (place_address) type或者new (place_address) type(initializer-list)
place_address必须是一个指针,initializer-list是类型的初始化列表
使用场景:
定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化。
new(obj)Date(3)等价于:Date* obj = new Date(3)

六、面试题

malloc/free和new/delete的区别【用法1-4和区别5-6】
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在释放空间前会调用析构函数完成空间中资源的清理

内存泄漏

  • 什么是内存泄漏,内存泄漏的危害
  1. 什么是内存泄漏:内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费
  2. 内存泄漏的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。
    内存泄漏是指针丢了
  • 内存泄漏分类(了解)
  1. 堆内存泄漏(Heap leak):堆内存指的是程序执行中依据须要分配通过malloc / calloc / realloc / new等从堆中分配的一块内存,用完后必须通过调用相应的 free或者delete
    删掉。假设程序的设计错误导致这部分内存没有被释放,那么以后这部分空间将无法再被使用,就会产生Heap Leak。
  2. 系统资源泄漏:指程序使用系统分配的资源,比方套接字、文件描述符、管道等没有使用对应的函数释放掉,导致系统资源的浪费,严重可导致系统效能减少,系统执行不稳定。
  • 如何避免内存泄漏
  1. 工程前期良好的设计规范,养成良好的编码规范,申请的内存空间记着匹配的去释放。ps:这个理想状态。但是如果碰上异常时,就算注意释放了,还是可能会出问题。需要下一条智能指针来管理才有保证。
  2. 采用RAII思想或者智能指针来管理资源。
  3. 有些公司内部规范使用内部实现的私有内存管理库。这套库自带内存泄漏检测的功能选项。
  4. 出问题了使用内存泄漏工具检测。ps:不过很多工具都不够靠谱,或者收费昂贵。
    内存泄漏非常常见,解决方案分为两种:1、事前预防型。如智能指针等。2、事后查错型。如泄漏检测工具。

补充知识:
编译器优化问题:(构造函数)【优化仅仅取决于编译器】

  • 匿名对象:生命周期仅仅这一行,【类:会在这一行调用构造函数和析构函数】类()【例如:Date()
  • 使用场景:当仅仅需要调用类里面一个函数就可以 类.函数(例如:Date().num(10)
  1. 一个表达式中:连续一个的构造+拷贝构造会被优化
    f(Date());//Date(),进行构造,然后立马又()拷贝构造,编译器进行优化。就直接优化为一个构造函数。【在一行表达式里面
  2. 一个表达式中:连续一个的连续的拷贝构造也会被优化
    Date ret = f(x);f(x)传值返回,临时变量,一个拷贝构造,赋值给
    ret一次拷贝构造。然后进行了优化。

总结

以上就是今天要讲的内容,本文详细的介绍了C/C++内存分布、动态内存管理方式、operator new和operator delete函数、new、delete实现原理。希望给友友们带来帮助!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法与数据结构(九)--并查集

并查集是一种树型的数据结构&#xff0c;并查集可以高校地进行如下操作&#xff1a; *查询元素p和元素q是否在同一组 *合并元素p和元素q所在的组 一.并查集结构 并查集也是一种树型结构&#xff0c;这种树的要求比较简单&#xff1a;1.每个元素都唯一的对应一个结点&#xff…

基于SSM的小说网站的设计与实现(论文+源码)_kaic

目 录 1 绪论................................................................................................... 1 1.1 项目背景................................................................................................................ 1 1.2 发展历程..…

Java学数据结构(2)——树Tree 二叉树binary tree 二叉查找树 AVL树 树的遍历

目录 引出什么是树Tree&#xff1f;树的实现二叉树binary tree查找树ADT——二叉查找树Binary Search Tree1.contains方法2.findMax和findMin方法3.insert方法4.remove方法&#xff08;复杂&#xff09;二叉查找树的深度 AVL(Adelson-Velskii和Landis)树——**平衡条件(balance…

Spring Boot(Vue3+ElementPlus+Axios+MyBatisPlus+Spring Boot 前后端分离)【三】

&#x1f600;前言 本篇博文是关于Spring Boot(Vue3ElementPlusAxiosMyBatisPlusSpring Boot 前后端分离)【三】的分享&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我…

【Jenkins】持续集成部署学习

【Jenkins】持续集成部署学习 【一】安装部署【1】Jenkins所处位置【2】Docker安装Gitlab&#xff08;1&#xff09;首先准备一台空的虚拟机服务器&#xff08;2&#xff09;安装服务器所需的依赖&#xff08;3&#xff09;Docker的安装&#xff08;4&#xff09;阿里云镜像加速…

VUE笔记(十)Echarts

一、Echarts简介 1、什么是echarts ECharts是一款基个基于 JavaScript 的开源可视化图表库 官网地址&#xff1a;Apache ECharts 国内镜像&#xff1a;ISQQW.COM x ECharts 文档&#xff08;国内同步镜像&#xff09; - 配置项 示例&#xff1a;echarts图表集 2、第一个E…

大语言模型之五 谷歌Gemini

近十年来谷歌引领着人工智能方向的发展&#xff0c;从TensorFlow到TPU再到Transformer&#xff0c;都是谷歌在引领着&#xff0c;然而&#xff0c;在大语言模型上&#xff0c;却被ChatGPT&#xff08;OpenAI&#xff09;抢了风头&#xff0c;并且知道GPT-4&#xff08;OpenAI&a…

红蓝攻防:浅谈削弱WindowsDefender的各种方式

前言 随着数字技术的日益进步&#xff0c;我们的生活、工作和娱乐越来越依赖于计算机和网络系统。然而&#xff0c;与此同时&#xff0c;恶意软件也日趋猖獗&#xff0c;寻求窃取信息、破坏系统或仅仅为了展现其能力。微软Windows&#xff0c;作为世界上最流行的操作系统&…

2023年03月 C/C++(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题:和数 给定一个正整数序列,判断其中有多少个数,等于数列中其他两个数的和。 比如,对于数列1 2 3 4, 这个问题的答案就是2, 因为3 = 2 + 1, 4 = 1 + 3。 时间限制:10000 内存限制:65536 输入 共两行,第一行是数列中数的个数n ( 1 <= n <= 100),第二行是由n个…

商品搜索网:连接您与各类商品的桥梁

导语&#xff1a;在如今信息爆炸的时代&#xff0c;购物已经不再是传统的实体店购买&#xff0c;而是通过互联网实现的线上购物方式。而要实现高效的线上购物&#xff0c;商品搜索引擎则成为我们的得力助手。作为国内垂直的商品搜索之一&#xff0c;为中国用户提供全面的数码电…

咸鱼之王俱乐部网站开发

我的俱乐部 最新兑换码 *注意区分大小写&#xff0c;中间不能有空格&#xff01; APP666 HAPPY666 QQ888 QQXY888 vip666 VIP666 XY888 app666 bdvip666 douyin666 douyin777 douyin888 happy666 huhushengwei888 taptap666 周活动 宝箱周 宝箱说明 1.木质宝箱开启1个…

缺页异常与copy-on-write fork

缺页异常需要什么 当发生缺页异常时&#xff0c;内核需要以下信息才能响应这个异常&#xff1a; 出错的虚拟地址&#xff08;引发缺页异常的源&#xff09; 当一个用户程序触发了缺页异常&#xff0c;会切换到内核空间&#xff0c;将出错的地址放到STVAL寄存器中&#xff0c;…

AndroidAGP8.1.0和JDK 17迁移之旅

AndroidAGP8.1.0和JDK 17迁移之旅 前言&#xff1a; 由于我最近写demo的直接把之前的项目从AGP4.2.2升级到8.1.0引发了一些列问题&#xff0c;这里记录一下&#xff0c;前面讲解过迁移DSL方式遇到的问题&#xff0c;这次升级8.1.0也比之前顺利多了&#xff0c;想看DSL迁移的可…

LeetCode——有效的括号

这里&#xff0c;我提供一种用栈来解决的方法&#xff1a; 思路&#xff1a;栈的结构是先进后出&#xff0c;这样我们就可以模拟栈结构了&#xff0c;如果是‘&#xff08;’、‘{’、‘[’任何一种&#xff0c;直接push进栈就可以了&#xff0c;如果是‘}’、‘&#xff09;’…

常见前端面试之VUE面试题汇总七

20. 对 vue 设计原则的理解 1.渐进式 JavaScript 框架&#xff1a;与其它大型框架不同的是&#xff0c;Vue 被设计 为可以自底向上逐层应用。Vue 的核心库只关注视图层&#xff0c;不仅易于上 手&#xff0c;还便于与第三方库或既有项目整合。另一方面&#xff0c;当与现代化的…

2023有哪些更好用的网页制作工具

过去&#xff0c;专业人员使用HTMLL、CSS、Javascript等代码手动编写和构建网站。现在有越来越多的智能网页制作工具来帮助任何人实现零代码基础&#xff0c;随意建立和设计网站。在本文中&#xff0c;我们将向您介绍2023年流行的网页制作工具。我相信一旦选择了正确的网页制作…

OpenGL —— 2.5、绘制第一个三角形(附源码,glfw+glad)(更新:纹理贴图)

源码效果 C源码 纹理图片 需下载stb_image.h这个解码图片的库&#xff0c;该库只有一个头文件。 具体代码&#xff1a; vertexShader.glsl #version 330 corelayout(location 0) in vec3 aPos; layout(location 1) in vec3 aColor; layout(location 2) in vec2 aUV;out ve…

如何搭建智能家居系统并通过内网穿透实现远程控制家中设备

文章目录 前言1. 安装Home Assistant2. 配置Home Assistant3. 安装cpolar内网穿透3.1 windows系统3.2 Linux系统3.3 macOS系统 4. 映射Home Assistant端口5. 公网访问Home Assistant6. 固定公网地址6.1 保留一个固定二级子域名6.2 配置固定二级子域名 前言 Home Assistant&…

(三)Linux中卸载docker(非常详细)

docker 卸载 使用yum安装docker 如需卸载docker可以按下面步骤操作&#xff1a; 1、停止docker服务 systemctl stop docker 2、查看yum安装的docker文件包 yum list installed |grep docker 3、查看docker相关的rpm源文件 rpm -qa |grep docker 4、删除所有安装的docke…

【JVM 内存结构丨栈】

栈 -- 虚拟机栈 简介定义压栈出栈局部变量表操作数栈方法调用特点作用 本地方法栈&#xff08;C栈&#xff09;定义栈帧变化作用对比 主页传送门&#xff1a;&#x1f4c0; 传送 简介 栈是用于执行线程的内存区域&#xff0c;它包括局部变量和操作数栈。 Java 虚拟机栈会为每…