【c++】c++内存管理

news2025/3/13 16:28:02

目录

  • c和c++的内存分布
  • 回顾C语言动态管理内存的方式
    • malloc
    • calloc
    • realloc
    • free
  • C++动态管理内存的方式
    • new和delete
    • operator new和operator delete
    • 定位new

c和c++的内存分布

在这里插入图片描述

回顾C语言动态管理内存的方式

malloc

void* malloc (size_t size);

malloc可以在堆上开辟指定内存的空间,参数是要开辟的空间的大小(单位字节),返回开辟好的空间的指针,注意返回的是无类型指针,需要强转一下指针类型,malloc也不会对开辟好的空间进行初始化。

calloc

void* calloc (size_t num, size_t size);

calloc同样是在堆上开辟指定内存的空间,但它要穿两个参数,num是要开辟的单元数,size是一个单元数的尺寸(单位字节),开辟的总空间大小就是num*size。calloc会对开辟的内存进行初始化,calloc同样返回无类型指针,需要强转。realloc的效率略低于malloc。

realloc

void* realloc (void* ptr, size_t size);

realloc可以更改开辟好的空间的大小,ptr给定需要改变的空间的地址,size为更改后的大小。realloc的扩容分为两种情况,原地扩和异地扩,因为开辟的空间要求是连续的,而堆上操作系统管理的内存并不一定就是连续的,当需要调整的空间后面有连续的空间且容纳的下扩容后的空间就直接原地扩容,以上条件不能满足时系统就会在另一边地方开辟size大小的空间,再把ptr上的数据拷贝过来完成拷贝。显然,原地扩的效率大于异地扩。当ptr为空指针时,realloc效果类似于malloc,当size为0时,realloc效果类似于free,但不推荐因此将realloc当malloc和free使用。calloc同样返回无类型指针,需要强转。

free


void free (void* ptr);

free可以释放动态开辟的内存,动态开辟内存后务必释放,不然会内存泄漏,一片空间只能释放一次。

C++动态管理内存的方式

new和delete

new和delete是c++中的关键字,new可以在堆上动态开辟内存并构造对象。delete可以释放new开辟的空间。使用方法如下。

int main()
{
	int* a = new int;//开空间不初始化
	int* b = new int(1);//开空间初始化
	int* c = new int[10];//开10个int类型的空间不初始化
	int* d = new int[10] {};//开10个int类型的空间初始化为0
	int* e = new int[10] {0};//开10个int类型的空间初始化为0
	int* f = new int[10] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};//开10个int类型的空间初始化为想要的数
	string* g = new string;//开类类型空间不初始化(调用默认构造)
	string* h = new string("Hello World");//开类类型空间初始化(调用构造)
	string* i = new string[10];//开10个类类型数组不初始化(调用10次默认构造)
	string* j = new string[10]{"jiunian"};//开10个类类型数组初始化了第一个(第一个调用构造,其他默认构造)
	delete a;
	delete b;//不是数组直接删
	delete[] c;
	delete[] d;
	delete[] e;
	delete[] f;//是数组delete后面加[]再删,注意此时delete[]为一个整体,delete[]本身为一个操作符。
	delete g;
	delete h;//类类型删除会调用析构函数
	delete[] i;
	delete[] j;//调用10次析构函数
	return 0;
}

new和delete与malloc、calloc、realloc、free的区别是:
1.new和delete是操作符,而malloc、calloc、realloc、free是函数。
2.new和delete在创建类类型对象以及销毁时会调用构造和析构函数。
3.new和delete不需要计算类型大小,也不用强转指针类型,malloc、calloc、realloc、free需要。

operator new和operator delete

/*
 operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败,
尝试执行空
间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。
*/
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);
}
/*
operator delete: 该函数最终是通过free来释放空间的
*/
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;
}
/*
free的实现
*/
#define   free(p) _free_dbg(p, _NORMAL_BLOCK)

operator new和operator delete是系统提供的全局函数,用来开辟内存空间。操作符new的底层就是通过operator new来申请空间的,操作符delete的底层就是通过operator delete来释放空间的。需要注意的是,operator new和operator delete仍然是通过malloc和free来进行内存的开辟与释放的。另外,需要注意new的作用不只是开辟空间,它还会对空间进行初始化,而delete也不只是释放空间,它还会清空数据。这点在类类型对象的内存开辟时就显得尤为明显,new会调用构造函数,delete会调用析构函数,所以不能简单地将new与operator new、delete与operator delete划等号,他们完全不是一个东西。new与delete是操作符,用法固定;operator new、operator delete是运算符重载函数,可以被重载,自定义成想要的空间开辟方式,如果在全局域或局部域中重载operator new和operator delete(注意重载了operator new就一定要重载对应的operator delete),原来的operator new和operator delete会被覆盖·,此时在这个域中使用new和delete会以自己定义好的方式开辟内存,但在局部域中重载operator new和operator delete可以通过::new、::delete的方式使用原来的operator new和operator delete,所以重载operator new和operator delete的操作建议在局部域中完成,冒然在全局域中重载覆盖原来的operator new和operator delete会然之前写的正常版本的new和delete失效。

定位new

new (address) Type(arguments);

定位new可以在开辟好的内存空间上调用构造函数初始化一个对象,定位new不再会先分配空间再初始化,因为是使用已分配的空间,所以定位new是直接调用构造函数。定位new常被用于内存池管理等方面。具体使用方法如下。

int main()
{
	std::string* buffer = (std::string*)malloc(sizeof(std::string) * 10);//开辟10个string的空间
	std::string* obj = new(buffer)std::string("Hello World");//取开头的一个初始化
	return 0;
}

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

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

相关文章

EtherNet/IP转Modbus TCP:新能源风电监控与分析实用案例

EtherNet/IP转Modbus TCP:新能源风电监控与分析实用案例 一、案例背景 在某新能源汽车电池生产线上,需要将采用EtherNet/IP协议的电池检测设备与采用ProfiNet协议的生产线控制系统进行集成,以实现对电池生产过程的全面监控和数据采集。 二、…

数字电路-基础逻辑门实验

基础逻辑门是数字电路设计的核心元件,它们执行的是基本的逻辑运算。通过这些基本运算,可以构建出更为复杂的逻辑功能。常见的基础逻辑门包括与门(AND)、或门(OR)、非门(NOT)、异或门…

国产编辑器EverEdit - 如虎添翼的功能:快速选择

1 快速选择 1.1 应用场景 快速选择适用于批量选择和修改的场景,比如:变量改名。 1.2 使用方法 1.2.1 逐项快速选择 将光标放置在单词前或单词中,选择主菜单查找 -> 快速选择 -> 快速选择或使用快捷键Ctrl D 注:光标放…

国内外网络安全政策动态(2025年1月)

▶︎ 1.国家互联网信息办公室发布《个人信息出境个人信息保护认证办法(征求意见稿)》 1月3日,国家互联网信息办公室发布《个人信息出境个人信息保护认证办法(征求意见稿)》。根据《意见稿》,个人信息出境个…

68页PDF | 数据安全总体解决方案:从数据管理方法论到落地实践的全方位指南(附下载)

一、前言 这份报告旨在应对数字化转型过程中数据安全面临的挑战,并提供全面的管理与技术体系建设框架。报告首先分析了数字化社会的发展背景,强调了数据安全在国家安全层面的重要性,并指出数据安全风险的来源和防护措施。接着,报…

AI大模型的文本流如何持续吐到前端,实时通信的技术 SSE(Server-Sent Events) 认知

写在前面 没接触过 SSE(Server-Sent Events),AI大模型出来之后,一直以为文本流是用 WebSocket 做的偶然看到返回到报文格式是 text/event-stream,所以简单认知,整理笔记博文内容涉及 SSE 认知,以及对应的 D…

Electron:使用electron-react-boilerplate创建一个react + electron的项目

使用 electron-react-boilerplate git clone --depth 1 --branch main https://github.com/electron-react-boilerplate/electron-react-boilerplate.git your-project-name cd your-project-name npm install npm start 安装不成功 在根目录加上 .npmrc文件 内容为 electron_…

Spring Boot三:Springboot自动装配原理

精心整理了最新的面试资料&#xff0c;有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 原理初探 pom.xml 核心依赖在父工程中 spring-boot-dependencies所有的jar包都在这里管理 我们在写或者引入一些依赖的时候&#xff0c;不需要指定版本 启动器 <…

2024 年 CSDN 博客之星年度评选:技术创作与影响力的碰撞(统计时间2025-02-17 11:06:06)

摘要&#xff1a;在技术的海洋里&#xff0c;每一位博主都像是一座独特的灯塔&#xff0c;用自己创作的光芒照亮他人前行的道路。2024 年 CSDN 博客之星年度评选活动&#xff0c;正是对这些灯塔的一次盛大检阅&#xff0c;让我们看到了众多优秀博主在技术创作领域的卓越表现以及…

Java零基础入门笔记:(3)程序控制

前言 本笔记是学习狂神的java教程&#xff0c;建议配合视频&#xff0c;学习体验更佳。 【狂神说Java】Java零基础学习视频通俗易懂_哔哩哔哩_bilibili Scanner对象 之前我们学的基本语法中我们并没有实现程序和人的交互&#xff0c;但是Java给我们提供了这样一个工具类&…

后端生成二维码,前端请求接口生成二维码并展示,且多个参数后边的参数没有正常传输问题处理

一、后端代码 1、controller GetMapping("/generateQRCode/{url}")ApiOperation(value "生成url链接二维码",notes "生成url链接二维码")public JsonResult<NewsQRCodeVo> generateQRCode(PathVariable String url,HttpServletRespons…

(8/100)每日小游戏平台系列

项目地址位于&#xff1a;小游戏导航 新增一个打地鼠游戏&#xff01; 打地鼠&#xff08;Whack-a-Mole&#xff09;是一款经典的休闲游戏&#xff0c;玩家需要点击随机出现的地鼠&#xff0c;以获取分数。游戏时间有限&#xff0c;玩家需要在规定时间内尽可能多地击中地鼠&am…

[Python人工智能] 五十.PyTorch入门 (5)快速搭建神经网络及模型保存

从本专栏开始,作者正式研究Python深度学习、神经网络及人工智能相关知识。前文讲解PyTorch构建分类神经网络。这篇文章将介绍如何利用PyTorch快速构建神经网络,之前的代码比较复杂,通过自定义Net类实现,本文通过Torch函数定义神经网络。前面我们的Python人工智能主要以Tens…

SpringBoot+Vue+数据可视化的动漫妆造服务平台(程序+论文+讲解+安装+调试+售后等)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统介绍 在当今数字化高速发展的时代&#xff0c;动漫产业迎来了前所未有的繁荣&#xff0c;动漫…

基于web的留守儿童网站的设计与实现

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

OpenCV中的边缘检测

边缘检测是图像处理和计算机视觉中的关键技术之一&#xff0c;旨在识别图像中像素强度发生显著变化的区域&#xff0c;这些区域通常对应于物体的边界或轮廓。边缘检测在机器视觉中具有重要的需求背景&#xff0c;主要体现在以下几个方面&#xff1a; 图像分割&#xff1a;边缘…

家里WiFi信号穿墙后信号太差怎么处理?

一、首先在调制解调器&#xff08;俗称&#xff1a;猫&#xff09;测试网速&#xff0c;网速达不到联系运营商&#xff1b; 二、网线影响不大&#xff0c;5类网线跑500M完全没问题&#xff1b; 三、可以在卧室增加辅助路由器&#xff08;例如小米AX系列&#xff09;90~200元区…

【前端学习笔记】Webpack

1.介绍 Webpack 是一个现代 JavaScript 应用程序的静态模块打包工具&#xff0c;它将 JavaScript、CSS、图片、字体等资源文件打包成一个或多个静态文件&#xff0c;以供浏览器使用。当 webpack 处理应用程序时&#xff0c;它会在内部从一个或多个入口点构建一个 依赖图(depend…

数据结构(陈越,何钦铭)第三讲 树(上)

3.1 树与数的表示 3.1.1 顺序查找 int SequentialSearch(List Tbl,ElementType K){int i;Tbl->Element[0]K;for(iTbl->Length;Tbl->Element[i]!K;i--);return i; } typedef struct LNode *List; struct LNode{ElementType Element[MAXSIZE];int Length; };3.1.2 二分…

【深度解析】图解Deepseek-V3模型架构-混合专家模型(MoE)

一、引言 最近非常火爆的DeepSeek-V3模型&#xff0c;是一个包含6710亿总参数的强大混合专家模型&#xff08;MoE&#xff09;&#xff0c;其中每个token激活370亿参数。该模型在DeepSeek-V2验证有效的核心架构基础上&#xff0c;采用多头潜在注意力&#xff08;MLA&#xff0…