【C++语言】动态内存管理

在这里插入图片描述


文章目录

  • 前言
  • 内存管理
    • 数据存储位置
    • C语言动态内存管理方式
    • C++动态内存管理方式:new/delete
    • operator new与operator delete函数
    • new和delete的实现原理
    • 定位new表达式(了解)
    • 常见面试题
  • 总结
  • C++语言系列学习目录


前言

本章要介绍的是动态内存管理:

  • 我们的定义的变量,储存位置在哪?
  • C动态内存管理方式:malloc/calloc/realloc/free
  • C++动态内存管理方式:new/delete
  • operator new与operator delete函数
  • new和delete的实现原理
  • 定位new表达式

内存管理

数据存储位置

不妨先来看看以下代码:看自己能否分清楚?

int globalVar = 1;static int staticGlobalVar = 1;void Test(){static int staticVar = 1;int localVar = 1;int num1[10] = { 1, 2, 3, 4 };char char2[] = "abcd";const char* pChar3 = "abcd";int* ptr1 = (int*)malloc(sizeof(int) * 4);int* ptr2 = (int*)calloc(4, sizeof(int));int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);free(ptr1);free(ptr3);}1. 选择题:
选项: A.栈  B.堆  C.数据段(静态区)  D.代码段(常量区)globalVar在哪里?____   staticGlobalVar在哪里?____staticVar在哪里?____   localVar在哪里?____num1 在哪里?____char2在哪里?____      *char2在哪里?___  pChar3在哪里?____     *pChar3在哪里?____ptr1在哪里?____       *ptr1在哪里?____2. 填空题:
sizeof(num1) = ____;
sizeof(char2) = ____;      strlen(char2) = ____;
sizeof(pChar3) = ____;     strlen(pChar3) = ____;
sizeof(ptr1) = ____;

答案如下:
在这里插入图片描述
如果有困难的话,就可以往下看了。

需要存储的一些数据它的存储方式如下:
在这里插入图片描述

int globalVar = 1;					//全局变量
static int staticGlobalVar = 1;		//静态变量void Test(){static int staticVar = 1;			//静态变量int localVar = 1;					//局部变量int num1[10] = { 1, 2, 3, 4 };		//数组 在哪声明 内容就在哪char char2[] = "abcd";				//数组 在哪声明 内容就在哪const char* pChar3 = "abcd";		//指针数组 指针在声明,指向内容在常量区int* ptr1 = (int*)malloc(sizeof(int) * 4);//指针在栈上 指针内容在堆上int* ptr2 = (int*)calloc(4, sizeof(int));int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);free(ptr1);free(ptr3);}

C语言动态内存管理方式

C语言的动态内存管理方式,我们其实已经了解了:malloc/calloc/realloc/free。就不过多介绍了,通过一个面试题来测试下自己的掌握情况: 【面试题】malloc/calloc/realloc的区别?

C++动态内存管理方式:new/delete

  1. 内置类型:
void Test1()
{//malloc~free// 动态申请一个int类型的空间int* ptr1 = (int*)malloc(sizeof(int));//动态申请一个int类型的空间并初始化为10int* ptr2= (int*)malloc(sizeof(int));if (ptr2 != NULL)*ptr2 = 10;// 动态申请10个int类型的空间int* ptr3 = (int*)malloc(sizeof(int)*10);free(ptr1);free(ptr2);free(ptr3);//new~delete// 动态申请一个int类型的空间int* ptr4 = new int;// 动态申请一个int类型的空间并初始化为10int* ptr5 = new int(10);// 动态申请10个int类型的空间int* ptr6 = new int[3];//动态申请4个int类型的空间并初始化为1,2,3,4int* ptr7=new int[4]{1,2,3,4};delete ptr4;delete ptr5;delete[] ptr6;delete[] ptr7;
}

在这里插入图片描述
其实不难发现malloc和new在内置类型上都只是开辟空间,差别其实不大,最多就是多写几行代码。

  1. 自定义类型:
class A
{
public:A(int a = 0): _a(a){cout << "A():" << this << endl;}~A(){cout << "~A():" << this << endl;}
private:int _a;
};
void Test2()
{//new~delete除了开辟空间,还会调用自定义类型的构造和析构函数。A* p1 = (A*)malloc(sizeof(A));A* p2 = new A(1);free(p1);delete p2;
}

在这里插入图片描述
从上方反汇编代码,我们可以清楚的看到,new调用了构造函数而delete调用了析构函数。而malloc和free并不会,这也是new和malloc的最大区别。

operator new与operator delete函数

那为什么有这样的区别呢?C语言过渡到C++,malloc到new,这会不会有什么关联呢?答案是肯定的。

1.new和delete是用户进行动态内存申请和释放的操作符
2. operator new 和operator delete是系统提供的全局函数
3.new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。
4. operator new底层是mallocl来申请空间的,operator delete底层也是通过free来释放空间的

在这里插入图片描述
我们进入封装内容看下:
在这里插入图片描述

不信,我们来看看operator new代码呗:

//operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间
//失败,尝试执行空间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。
void* __CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{// try to allocate size bytesvoid* 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_FINALLYreturn;
}
/*
free的实现
*/
#define   free(p)               _free_dbg(p, _NORMAL_BLOCK)

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

new和delete的实现原理

  • 整体过程:
    在这里插入图片描述
    new的实现:
  • 开辟空间:调用operator new 开辟空间,开辟的是自定义类型大小的空间;
  • 构造函数:主要是申请资源,也就是_array的空间申请;
    在这里插入图片描述
    delete的实现:
  • 析构函数:先释放_array申请的资源;
  • 释放空间:然后调用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表达式(了解)

注意:这已经不是new了,而是new这个关键字的一个用法

new可以显示调用构造函数和析构函数,以下代码为定位new来模拟new和delete的实现过程。

int main()
{// p1现在指向的只不过是与A对象相同大小的一段空间,还不能算是一个对象,因为构造函数没有执行A* p1 = (A*)malloc(sizeof(A));new(p1)A;  // 注意:如果A类的构造函数有参数时,此处需要传参p1->~A();free(p1);A* p2 = (A*)operator new(sizeof(A)); //开辟空间new(p2)A(10);	//显式调用构造函数p2->~A();		//显式调用析构函数operator delete(p2); 				 //释放空间return 0;
}

常见面试题

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在释放空间前会调用析构函数完成 空间中资源的清理

总结

本节主要是介绍空间内的存储,以及一些管理动态内存的方法。最重要的是new和delete的用法以及它的原理。


C++语言系列学习目录

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络工程师----第二十七天

计算机基 第四章&#xff1a;网络层 网络层提供服务的特点&#xff1a;网络层向上只提供简单的、无连接的、尽最大努力交付的数据报服务&#xff0c;不保证可靠通信。 网际协议IP&#xff1a; *地址解析协议ARP(Address Resolution Protocol) *网际控制报文协议ICMP(Inter…

Android 集成Bugly完成线上的异常Exception收集及处理

文章目录 &#xff08;一&#xff09;添加产品APP&#xff08;二&#xff09;集成SDK&#xff08;三&#xff09;参数配置权限混淆 &#xff08;四&#xff09;初始化 &#xff08;一&#xff09;添加产品APP 一&#xff09;在个人头像 -> 我的头像 -> 新建产品 二&…

【Pytorch】7.使用Module模块搭建简易神经网络

什么是Moudel模块 torch.nn中的module是PyTorch中用于构建神经网络模型的基本单元。它包含了各种神经网络层、激活函数、损失函数等&#xff0c;可以通过组合不同的module来构建复杂的神经网络模型。每个module都包含了参数和方法&#xff0c;可以进行前向传播和反向传播等操作…

地平线X3开发板配置wifi调试

1. 系统镜像制作 系统镜像的制作依赖bsp与补丁包&#xff0c;bsp在天工开物全量包中&#xff1a;https://developer.horizon.ai/resource 补丁下载链接&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1YKcOWL0EpboGq-SnqwIGeQ 提取码&#xff1a;b6lf 补丁包中有详细…

软件库V1.5版本iApp源码V3

软件库V1.5版本iApp源码V3 配置教程在【mian.iyu】的【载入事件】 更新内容&#xff1a; 1、分类对接蓝奏&#xff08;免费&#xff0c;付费&#xff0c;会员&#xff0c;广告&#xff09;&#xff0c;支持蓝奏文件描述设置为简介&#xff08;改动&#xff1a;首页.iyu&#…

【JavaEE】HTTP 协议

文章目录 一、HTTP 协议1、HTTP 是什么2、理解 "应用层协议"3、理解 HTTP 协议的工作过程4、HTTP 协议格式5、HTTP 请求 (Request)5.1 认识 URL 6、 二、HTTPS1、HTTPS是什么2、"加密" 是什么3、HTTPS 的工作过程3.1 对称加密3.2 非对称加密3.3 证书3.4 完…

新手做抖店一般多久出单?想尽快出单需要做什么准备工作?

大家好&#xff0c;我是电商糖果 有不少刚开店的朋友&#xff0c;喜欢搜索&#xff0c;咨询多久出单的问题。 根据糖果做店四年多的经验来说&#xff0c;新手运营新店&#xff0c;只要操作思路正确&#xff0c;一般是一周左右就会出单&#xff0c;三到四周左右&#xff0c;店…

NSSCTF中的1zjs、作业管理系统、finalrce、websign、简单包含、Http pro max plus

目录 [LitCTF 2023]1zjs [LitCTF 2023]作业管理系统 [SWPUCTF 2021 新生赛]finalrce exec()函数&#xff1a;php中exec介绍及使用_php exec-CSDN博客​​​​​​ 资料参考&#xff1a;RCE(远程命令执行)绕过总结_rce绕过-CSDN博客 [UUCTF 2022 新生赛]websign [鹏城杯 …

局域网监控软件有哪些:好用的局域网桌面监控软件神器分享

如何有效地监控和管理内部员工的计算机使用行为&#xff0c;防范潜在的安全风险&#xff0c;提高工作效率&#xff0c;是众多企业管理者关注的焦点。 而一款优秀的局域网桌面监控软件无疑能为企业的IT治理提供有力支撑。 小编在此给大家推荐一款好用的局域网桌面监控软件——域…

克服亏损的负面影响 学学现货白银止损的方法

一个多月以前&#xff0c;现货黄金的上涨还十分强劲&#xff0c;一度还逼近历史的高位30大关。但是我们看近半个月以来&#xff0c;现货白银价格出现了调整。很多在高位买入的投资者都承受了较大的亏损&#xff0c;这时候就凸显出了现货白银止损的作用。如果投资者能够通过近期…

销量?模糊销量?精准销量?如何获取淘宝商品销量数据接口

淘宝爬虫商品销量数据采集通常涉及以下几个步骤&#xff1a; 1、确定采集目标&#xff1a;需要明确要采集的商品类别、筛选条件&#xff08;如天猫、价格区间&#xff09;、销量和金额等数据。例如&#xff0c;如果您想了解“小鱼零食”的销量和金额&#xff0c;您需要设定好价…

探索数据结构:堆的具体实现与应用

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;数据结构与算法 贝蒂的主页&#xff1a;Betty’s blog 1. 堆的概念 堆(Heap)是计算机科学中一类特殊的数据结构。堆通常是一个…