C++中内存的动态管理

news2024/10/6 5:56:44

我们在C语言中了解到可以在栈区动态开辟空间,并且用完要进行释放,防止内存泄漏。

引入

C++中也有可以进行动态开辟空间和释放空间的操作符new 、delete,虽然C++中也可以用malloc、calloc、realloc、free函数,但是C++中引入了类,而类中会默认生成构造函数和析构函数,如果你想在堆上开辟类类型的空间继续malloc的话,那么该空间的内容就不会自动调用构造函数,而free也不会自动调用析构函数,因为你创建的类指针变量存的是地址,并不是自定义类型,所以程序结束时也不会自动调用析构函数。

对内置类型的内存管理

int main()
{
	// 动态申请一个int类型的空间,不初始化
	int* ptr1 = new int;

	// 动态申请一个int类型的空间并初始化为10
	int* ptr2 = new int(10);

	// 动态申请3个int类型的空间,并初始化为1 2 3
	int* ptr3 = new int[3] {1, 2, 3};

	delete ptr1;//释放单个空间
	delete ptr2;

	delete[] ptr3;//释放连续空间
	return 0;
}

申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用
new[]和delete[]。其实此时对于内置类型而言new与delete相较于malloc与free实现的功能其实是一样的。

对自定义类型的内存管理 

class A
{
public:
	A(int a = 0)
		: _a(a)
	{
		cout << "A():" << this << endl;
	}
	~A()
	{
		cout << "~A():" << this << endl;
	}
private:
	int _a;
};
int main()
{
	A* p1 = (A*)malloc(sizeof(A));
	//A* p2 = new A(1);
	free(p1);
	//delete p2;

	return 0;
}

运行结果:

int main()
{
	//A* p1 = (A*)malloc(sizeof(A));
	A* p2 = new A(1);
	//free(p1);
	delete p2;

	return 0;
}

运行结果:new空间时自动调用构造函数,delete空间时调用析构函数

operator new与operator delete函数

其实操作符new、delete也不是单纯的可以直接实现的,其实,在它们内部还调用着对应的函数operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。

operator new

其实operator new也是通过调用malloc函数实现的,在堆区开辟空间,但是在malloc的基础之上稍稍加了修饰,malloc调用失败会返回NULL,而operator new再次加了判断条件

while ((p = malloc(size)) == 0)//C++中NULL就是0

此时如果为空的话,就会抛异常报错。

 

operator delete

其实向operator new一样,operator delete是通过free来释放空间的。

new和delete的实现原理

其实new和delete操作符也不是仅仅就调用了operator new和operator delete那么简单,其实实际上还调用了类的构造函数,而delete还调用了类的析构函数(delete是先调用析构函数,再调用operator delete函数释放创建的空间)

  • new A[N]的原理

1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对
象空间的申请
2. 在申请的空间上执行N次构造函数

  • delete[]的原理

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

 

 未匹配报错

class A
{
public:
	A(int a = 0)
		: _a(a)
	{
		//cout << "A():" << this << endl;
	}
	~A()
	{
		//cout << "~A():" << this << endl;
		//_a = 0;
	}
private:
	int _a;
};
int main()
{
	A* p = new A[5];
	delete p;

	return 0;
}

此时delete未与new[]匹配,其实应该delete[]p来释放空间的,此时其实就是未匹配的原因报错的。

实际上当你执行:

	A* p = new A[5];

并不是开辟5个A类型大小的空间,实际上会多开辟四个字节存放你要开辟的空间的数字,也就是5,存着的目的也就是通过指针偏移得到这四个字节的数据,从而调用多少次析构函数,所以必须要用delete[]p来释放才行(实际上[]里接收的就是四字节空间存的5)。但是调用operator delete时,指针会偏移指向最前面,释放的所有的空间,包括前面的四个字节。

所以 用delete p来释放空间就肯定会报错啊,不仅仅不会调用5次析构函数,而且主要还不会将前面四字节空间释放,所以就


 

其实我演示的是在x86环境下的,所以就多开辟四字节空间,试试看在x64环境下,貌似是多开辟8字节空间。

 这里A占4个字节,-1就是偏移四字节。

 

 



其实你不写析构函数的话,编译器也不会报错

class A
{
public:
	A(int a=0)
		: _a(a)

	{}
private:
	int _a;
};
int main()
{
	A* p = new A[5];
	delete p;

	return 0;
}

因为编译器进行优化了,没写析构函数,编译器默认生成,但是默认生成也不会执行什么命令,此时编译器就会进行优化,所以就不会再多开辟字节去存放开辟空间的数字了,所以调用operator delete时就是正确的,不会报错,但是可能会内存泄漏(由于没有调足够的析构函数)



欢迎各位莅临指导!!!

 

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

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

相关文章

宋浩概率论笔记(二)随机变量

本章节内容较多&#xff0c;是概率论与数理统计中最为重要的章节&#xff0c;对于概率密度和分布函数的理解与计算要牢牢掌握&#xff0c;才能在后期的学习中更得心应手。

小研究 - 微服务系统服务依赖发现技术综述(一)

微服务架构得到了广泛的部署与应用, 提升了软件系统开发的效率, 降低了系统更新与维护的成本, 提高了系统的可扩展性. 但微服务变更频繁、异构融合等特点使得微服务故障频发、其故障传播快且影响大, 同时微服务间复杂的调用依赖关系或逻辑依赖关系又使得其故障难以被及时、准确…

【Azure上云项目实战】 合规性的身份验证与访问控制:在 Azure 中实现符合 PCI DSS 要求的架构设计

文章目录 一、开篇写在前面二、项目背景及介绍三、Azure PCI DSS 项目架构及组件四、身份验证、访问控制4.1 三层防御控制4.2 三层部署结构 五、跳板机六、与 PCI DSS 要求的关系七、该篇总结&#xff08;重要&#xff09;写在文末 一、开篇写在前面 各位博客阅读者们以及对云…

【A200】Ubuntu18.04 + ROS-Melodic + 比业电子VISIOSCAN雷达 评测

大家好&#xff0c;我是虎哥&#xff0c;朋友介绍&#xff0c;有一款单线激光雷达&#xff0c;25米的检测距离&#xff0c;有80HZ的扫描频率&#xff0c;而且角度分辨率最高可以到0.1&#xff0c;这个参数我确实没有见过&#xff0c;所以立刻着手从厂家那申请到了VISIOSCAN雷达…

Android的Handler消息通信详解

目录 背景 1. Handler基本使用 2. Handler的Looper源码分析 3. Handler的Message以及消息池、MessageQueue 4. Handler的Native实现 4.1 MessageQueue 4.2 Native结构体和类 4.2.1 Message结构体 4.2.2 消息处理类 4.2.3 回调类 4.2.5 ALooper类 5. 总结&…

轻量级目标检测模型NanoDet-Plus微调、部署(保姆级教学)

前言 NanoDet-Plus是超快速、高精度的轻量级无锚物体检测模型&#xff0c;github项目文件。可以在移动设备上实时检测。其主要特点是 超轻量&#xff1a;模型文件仅980KB(INT8)、1.8MB(FP16)超快&#xff1a;移动ARM CPU上97fps&#xff08;10.23ms&#xff09;高精度&#xf…

C++内存管理(动态内存开辟)

我们在C语言当中想要使用堆区的空间的时候就需要使用malloc函数进行手动的申请&#xff0c;但是我们在申请的时候需要手动进行计算&#xff0c;经过计算之后还需要进行判空操作&#xff0c;并且还不能进行任意值的初始化。这一切看起来在学习完C当中的动态开辟之前显得很正常&a…

最新版本mac版Idea 激活Jerbel实现热部署

1.环境准备 1.安装docker desktop 客户端创建本地服务 2.创建guid 3.随便准备一个正确格式的邮箱 2.具体操作 1.通过提供的镜像直接搭建本地服务 docker pull qierkang/golang-reverseproxy docker run -d -p 8888:8888 qierkang/golang-reverseproxy2.guid 通过如下网址直…

小C说历史(人物介绍第一篇):传奇人物Linus Torvalds 缔造Linux和Git

传奇人物Linus Torvalds 缔造Linux和Git Linus Torvalds&#xff0c;1969年12月28日出生于芬兰的赫尔辛基&#xff0c;Linux核心的创作者。当Linus十岁时&#xff0c;他的祖父&#xff0c;赫尔辛基大学的一位统计教授&#xff0c;购买了一台Commodore VIC-20计算机。Linus帮助他…

Mybatis-Plus面向实用知识点——结合SpringBoot

目录 环境配置基本流程各类中的方法BaseMapperIServiceCOUNTGETQueryListPageRemoveSaveUpdate 环境配置 参考java项目各框架环境配置 基本流程 创建Mapper Mapper public interface MyMapper extends BaseMapper<Entity>{}创建Service public interface MyService …

【娱乐圈明星知识图谱2】信息抽取

目录 1. 项目介绍 2. 信息抽取介绍 3. ChatGPT 信息抽取代码实战 4. 信息抽取主逻辑 5. 项目源码 1. 项目介绍 利用爬虫项目中爬取的大量信息 【娱乐圈明星知识图谱1】百科爬虫_Encarta1993的博客-CSDN博客娱乐圈明星知识图谱百度百科爬虫百度百科爬虫百度百科爬虫百度百…

【vue】 vue2 监听滚动条滚动事件

代码 直接上代码&#xff0c;vue单文件 index.vue <template><div class"content" scroll"onScroll"><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容…

java 定时任务不按照规定时间执行

这里写目录标题 使用异步启动可能出现的问题排查代码中添加的定时任务步骤是否正确排查是否任务阻塞&#xff0c;如果定时任务出现异常阻塞后&#xff0c;将不会在次执行java中多个Scheduled定时器不执行为了让Scheduled效率更高&#xff0c;我们可以通过两种方法将定时任务变成…

springboot 整合代码块实现访问

一 springboot整个代码块实 2.访问

补充JDK源码-IDEA集成工具

在阅读JDK8源码的时候发现&#xff0c;只有一小部分常用包是存在源码及其注释的&#xff0c;而很多内部包是没有源码&#xff0c;class文件在阅读的时候对阅读者十分不友好。在网上搜集了很多资料都没有解决问题。 解决问题办法&#xff1a;参考文档。本文主要是根据这篇文章记…

语义检索系统【一】:基于无监督预训练语义索引召回:SimCSE、Diffcse

搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术细节以及项目实战(含码源) 专栏详细介绍:搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术…

VB6: 安装界面中文乱码,打开项目中文乱码

Win11环境下的VB6开发&#xff0c;遇到中文乱码问题。 1.在安装VB6开发环境的时候&#xff0c;对话框各种乱码 2.安装完&#xff0c;或者用绿色版VB6&#xff0c;打开现有项目的时候&#xff0c;中文内容出现乱码 解决方法&#xff1a; 参考这篇文章&#xff1a;Windows: 文…

cc2652主协处理器分时控制同一个外设的问题

问题已提交TI论坛&#xff0c;我是提交到的中文论坛&#xff0c;然后fae给转到英文论坛了。 简单描述就是&#xff0c;怎么让这个单片机一会用主处理器控制SPI设备&#xff0c;一会再用协处理器控制同一个设备。 主处理器的spi配置使用 CCS studio配置的 协处理器使用Sensor Co…

监控对象都有哪些分类

1、业务监控 这类指标是管理层非常关注的&#xff0c;代表企业营收&#xff0c;或者跟客户主流程相关&#xff0c;类似 BI 数据。不过相比 BI 数据&#xff0c;业务监控指标有两点不同。 对精确度要求没有那么高&#xff1a;因为监控只要发现趋势异常就可以&#xff0c;至于是…

Spring Boot的自动配置原理

一.原理解释 Spring Boot的自动配置是Spring框架的一个重要特性&#xff0c;它旨在简化应用程序的开发和部署过程。自动配置通过基于类路径中的依赖关系和配置文件内容来预先配置Spring应用程序的各种组件和功能。这样&#xff0c;我们可以在无需显式配置大量参数的情况下&…