C++入门全集(5):内存管理

前言

一、内存区域划分

二、C++的内存管理方式

2.1 对内置类型

2.2 对自定义类型

三、new和delete的底层实现

四、new和delete的原理

五、定位new

六、malloc/free和new/delete

 

前言

在C++中,内存管理是不可避免的一门必修课。C++对内存的自由度使其获得了更高的性能,以及更高的难度。内存泄漏往往是每个C++学习者绕不开的错误, 而内存管理的水平高低也能看出一个编程者的能力。

在C语言中,我们学习了malloc、calloc、realloc和free,对C语言的内存管理也有了大致的接触。

本文中我们来学习C++中的内存管理


一、内存区域划分

C++中,程序的内存区域从低地址到高地址划分如下:

  • 代码段:存储可执行程序的代码和只读常量
  • 数据段:存储已初始化的全局变量和静态变量
  • 堆:用于程序运行时动态内存分配,从低地址向高地址增长
  • 栈:又叫堆栈,存储非静态局部变量/函数参数和返回值等,从高地址向低地址增长

例如: 

globalVar是全局变量,staticGlobalVar是静态全局变量,存储在数据段中;

staticVar是静态局部变量,存储在数据段中;

localVar、num1、char2、pChar3和ptr1都是局部变量,存储在栈中;

*char2是在栈帧中的空间,存储在栈中;*pChar3是常量字符串abcd的第一个字符,在代码段中;

malloc动态开辟出的空间存储在堆上。


二、C++的内存管理方式

2.1 对内置类型

C++兼容C语言,所以C语言的内存管理方式在C++中可以正常使用

相比C语言使用malloc和free等函数进行内存管理,C++提出了自己的内存管理方式:通过newdelete操作符进行动态内存管理

以上是C语言和C++动态申请一个类型大小的空间、多个类型大小的空间和内存释放的方式

 

实际上,面对内置类型,用malloc和new没有本质的区别,最大的区别在于:new可以初始化

在默认情况下,new和malloc一样不会对内置类型进行初始化,但是我们可以提出需求

注意区分初始化和申请多个元素,一个是圆括号一个是方括号

我们new一个数组时也可以进行初始化,例如:

C++不推荐使用malloc和free,我们最好使用new和delete,并且记得务必匹配使用。

对于内置类型,malloc和new区别不大。new是为了自定义类型而生的。

2.2 对自定义类型

我们在创建自定义类型对象的时候,需要调用析构函数,销毁时需要调用构造函数

而如果我们使用malloc和free的话,是不会调用这两个函数的

使用new来为自定义类型对象申请空间,编译器才会调用构造函数为对象初始化;用delete为自定义类型对象释放空间,才会调用析构函数。


三、new和delete的底层实现

new和delete并不是函数,而是用户进行动态内存申请和释放的操作符

但是其底层还是需要调用函数。

new在底层调用operator new这个函数来申请空间,delete在底层调用operator delete函数来释放空间。operator new和operator delete是系统提供的全局函数。

注意:这两个函数不是new和delete的重载函数!!!

虽然函数名中带operator,但并不是重载函数,具有很强的误导性。

我们来看看这两个函数的实现:

void* __CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
	// try to allocate size bytes
	void* p;
	while ((p = malloc(size)) == 0)
		if (_callnewh(size) == 0)
		{
			// report no memory
			// 如果申请内存失败了,这里会抛出bad_alloc 类型异常
			static const std::bad_alloc nomem;
			_RAISE(nomem);
		}

	return (p);
}

void operator delete(void* pUserData)
{
	_CrtMemBlockHeader* pHead;

	RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));

	if (pUserData == NULL)
		return;

	_mlock(_HEAP_LOCK);  /* block other threads */
	__TRY

		/* get a pointer to memory block header */
		pHead = pHdr(pUserData);

	    /* verify block type */
		_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));

		_free_dbg(pUserData, pHead->nBlockUse);

	__FINALLY
		_munlock(_HEAP_LOCK);  /* release other threads */
	__END_TRY_FINALLY

	return;
}

通过上面两个全局函数的实现,可以看出operator new实际上也是通过malloc来申请空间的,如果malloc申请空间成功就直接返回,如果失败则执行用户提供的应对措施,如果用户提供该措施则继续申请空间,否则抛出异常。

operator delete最终也是通过free来释放空间的。就像引用的底层也是用指针的方式实现的。

需要注意,构造函数和析构函数不是通过这两个函数来调用的。 


四、new和delete的原理

(1)new的原理

  • 调用operator new函数申请空间
  • 在申请的空间上执行构造函数,完成对象的构造

(2)delete的原理

  • 在空间上执行析构函数,完成对象中资源的清理工作
  • 调用operator delete函数释放对象的空间

(3)new T[N]的原理

  • 调用operator new[]函数,而operator new[]函数实际上又会调用operator new函数完成N个T类型对象的空间申请
  • 在申请的空间上执行N次构造函数

(4)delete[]的原理

  • 在空间上执行N次析构函数,完成N个对象的资源清理
  • 调用operator delete[]函数,而operator delete[]函数又会调用operator delete函数来释放空间


五、定位new

定位new表达式用于在已分配的原始内存空间调用构造函数初始化一个对象

大部分情况下,我们直接使用new来给对象分配空间

但是有时候需要进行性能优化,我们会直接从内存池中拿空间,使用malloc开空间

平时我们需要分配空间时从操作系统——堆上开空间,每次有需求就要开一次,但是内存池一次从堆上拿走一个内存块(大块空间),就不需要我们重复的去申请,减少了与堆的交互,提升了效率

如果是自定义的对象,对于malloc出来的空间,则需要使用定位new来显式的调用构造函数进行初始化

使用格式:

构造函数不需要传参时:new(指针)类名

构造函数需要传参时:new(指针)类名(参数)

例如:

或者:

销毁的方式:


六、malloc/free和new/delete

malloc/free和new/delete的共同点在于:都是从堆上申请空间,并且需要用户手动释放

不同点在于:

  1. malloc和free是函数,new和delete是操作符
  2. malloc申请的空间不会初始化,new可以进行初始化
  3. malloc申请空间时需要自行计算要开的空间大小,new只需要空间类型和元素个数
  4. malloc的返回类型为void*,需要强制转换类型,new不需要
  5. malloc申请空间失败时返回空指针,需要判空,new失败时抛出异常,需要捕获
  6. 为自定义类型对象申请空间时,malloc和free不会调用构造函数和析构函数,而new和free会调用

如果文章有误,欢迎在评论区指出

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

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

相关文章

面向对象编程-Java

面向对象编程 面向对象 & 面向过程 面向过程思想(线性思维) 步骤清晰简单,第一步做什么,第二步做什么……面向过程适合处理一些较为简单的问题 面向对象思想 物以类聚,分类的思维模式,思考问题首先会解…

mybatis的xml文件如何配置能被识别

为了让MyBatis能够识别和使用XML Mapper文件,你需要确保这些文件被正确放置和配置。下面是确保MyBatis XML Mapper文件被识别的步骤: 1. 正确放置XML Mapper文件 通常,XML Mapper文件应该放在src/main/resources目录下。为了更好的组织这些…

【STM32+OPENMV】二维云台颜色识别及追踪

一、准备工作 有关OPENMV最大色块追踪及与STM32通信内容,详情见【STM32HAL】与OpenMV通信 有关七针OLED屏显示内容,详情见【STM32HAL】七针OLED(SSD1306)配置(SPI版) 二、所用工具 1、芯片:STM32F407ZGT6 2、CUBEMX配置软件 3、KEIL5 4…

VUE读取静态文件技巧

背景: 现在有一个文件123.jpg在assets目录,我需要在bbb.vue里面去引用他,直接使用../方法无法获取该文件,且页面不能正常显示。文件目录如下: 解决办法:使用require方法: require(../assets/1…

基于springboot+vue的酒店管理系统

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 ​主要内容:毕业设计(Javaweb项目|小程序|Pyt…

【STM32F103】WDG看门狗

本系列在之前介绍时钟树的文章中有稍微提一下看门狗WDG(Watch Door Dog)。 简单来说,可以当成是一个计数器,一旦这个计数器溢出则单片机复位。因为我们需要每隔一段时间就把这个计数器的值清零(喂狗)。 I…

C++命名空间

在C/C中,变量,函数和和类这些名称都存在于全局作用域中,可能会导致很多冲突,使用命名空间的目的是对标识符的名称进行本地化,避免命名冲突或名字污染,namespace关键字就是解决这种问题的。如下程序并无问题…

低代码平台开发实践:基于React的高效构建与创新【文末送书-29】

文章目录 背景低代码平台简介基于React的优势低代码平台的实际应用 低代码平台开发实践:基于React【文末送书-29】 背景 随着技术的不断进步和业务需求的日益复杂,低代码平台成为现代软件开发领域中备受关注的工具之一。在这个快节奏的时代,…

C语言——结构体(位段)、联合体、枚举

hello,大家好!我是柚子,今天给大家分享的内容是C语言中的自定义类型结构体、联合体以及枚举,有什么疑问或建议可以在评论区留言,会顺评论区回访哦~ 一、结构体 struct a.结构体声明 不同于数组的是,结构…

16:00面试,16:06就出来了,问的问题过于变态了。。。

从小厂出来,没想到在另一家公司又寄了。 到这家公司开始上班,加班是每天必不可少的,看在钱给的比较多的份上,就不太计较了。没想到2月一纸通知,所有人不准加班,加班费不仅没有了,薪资还要降40%…

C++对象内存模型布局详解

目录 本文主要内容如下: 最后还有一些问题: 一、理解虚函数表 二、对象模型概述 三、继承下的C对象模型 单继承: 多继承: 一般的多继承(非菱形继承): 菱形继承: 五、虚继承…

如何创建一个VUE3项目并使用Element UI插件

1.确保已经安装了Node: win R 打开控制面板,输入“node -v”回车。出现版本号信息,则安装成功,否则请移步安装。 Node.js安装及环境配置(简单易懂!)_building: c:\program files\nodejs\node…

基于SSM的学科竞赛管理系统。Javaee项目。ssm项目。

演示视频: 基于SSM的学科竞赛管理系统。Javaee项目。ssm项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构,通过Spring SpringMvcMybatisVueLayuiElemen…

我的第②个出海工具站 - 2024年50个出海工具站计划

为了大家更好的使用各种出海工具。我上线了一版 出海工具导航 站点,经常使用的可以收藏下,我文内使用的网站都集成在了这里,非常使用。 随着AIGC的到来,2024年到了海外工具回暖的一年。今年计划上线50款出海工具站计划&#xff0c…

嵌入式工程师函数变量,常用的命名规则(参考学习)

很多工程师不注重平时编码习惯,比如命名规则,一会大写、一会小写,一会中文拼音,一会下划线等,导致自己写的代码自己都看不懂了。 今天就来分享一点关于软件代码常见的几种命名规则。 匈牙利命名法 匈牙利命名法广泛应…

西安雁塔未来人工智能计算中心算力成本分析

先看一例旧闻:西部“最强大脑”落户雁塔——30亿亿次超算能力助力创新之城建设 其中提到一期算力为 300PFLOPS FP16(每秒30亿亿次半精度浮点计算),项目总投资约为19亿元。 这个算力是什么概念呢? 我们以深度学习训练中…

使用sunshine和moonlight实现远程游戏串流

过年回家想要打游戏,但是苦于家里没有电脑,又没办法把电脑搬回去,于是想到了使用串流的方式。 实现串流的软件有多种: moonlight。因为仅实现了 NVIDIA 的游戏串流协议,所以只支持 N 卡。Steam Link。支持 steam 的游…

第五十回 插翅虎枷打白秀英 美髯公误失小衙内-mayfly-go:web 版 linux、数据库等管理平台

晁盖宋江和吴用到山下迎接雷横上山,宋江邀请雷横入伙,雷横以母亲年事已高为由拒绝了。 雷横回到郓城,听李小二说从东京新来了个表演的叫白秀英,吹拉弹唱跳,样样精通,于是雷横和李小二一起到戏院去看演出。…

什么是AJAX?它的运用场景有哪些?

文章目录 前言一、什么是AJAX二、AJAX原理是什么三、为什么需要AJAX四、AJAX的使用五、AJAX的应用场景 前言 AJAX 即 Asynchronous Javascript And XML(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。 AJAX 是一种用于创…

首尔之春在线资源最新电影1080p高清

打开下面这个链接就可以看到 首尔之春在线资源最新电影1080p高清 如果链接打不开,就复制下面的网址到浏览器打开 https://www.zhufaka.cn/liebiao/A09504AE3BF8BD06 用阿里云盘下载,下载完成之后,用迅雷播放 首尔之春在线资源最新电影10…