“池化技术” - 深度剖释底层内存管理细节,明晰“池化技术”内存管理技术_内存池化

🌰举个例子:

  • 1️⃣内存申请:
//动态申请40个字节空间大小的空间
int\* p = (int\*)malloc(sizeof(int) \* 10);

//动态申请大小为sizeof(int)的空间
int\* p1 = new int;

//动态申请大小为sizeof(int)\*10的空间
int\* p2 = new int[10];

  • 2️⃣内存释放:
free(p);

delete p1;

delete[] p2;

特别注意:

  • 我们可以在申请空间的时候,同时对空间进行初始化
//动态申请大小为sizeof(int)的空间,并初始化为0
int\* p1 = new int();

//动态申请大小为sizeof(int)的空间,并初始化为1
int\* p2 = new int(1);

//动态申请大小为sizeof(int)\*10的空间,并初始化为0
int\* p3 = new int[10](0);

  • 但注意,并不存在new int[10](1)的存在,因为标准不支持
  • 但在C++11中支持了另外一种初始化方式:列表初始化
int\* p = new int[4]{1, 2, 3, 4};

  • 在对内存进行释放的时候,delete操作符需要与new操作符相互匹配:

    • 如果申请的是单个元素的空间【new 数据类型】,则delete 数据类型即可
    • 如果申请的是连续的空间【new 数据类型[数据个数]】,则需要delete[] 数据类型
    • 如果类型不匹配,有可能会出现不必要的错误,所以我们书写的时候尽可能类型相互匹配

可能我们会有疑惑: 为什么可以在内存申请的时候就进行初始化

👉以下我们就能深入解答此问题啦~


🥐Ⅱ.针对不同类型的处理

💡new和delete会针对不用类型做不同的处理:

  • 引入概念:new的底层虽然是malloc,但是还有有一定区别的

    • 即正是因为C++中引入了类和对象的概念,使得new表面上看是根据给的数据类型和数据个数去判断开辟多大的空间
    • 其实本质是:在所申请的空间中构造了数据个数个数据类型的对象
  • 所以,new和delete操作符会根据创建的对象类型是自定义类型还是内置类型,去做不同的操作:

    • 对于内置类型

      • new和malloc的使用几乎没有区别,相当于多了个对象的概念(即在申请内存的时候可以进行初始化)
    • 对于自定义类型

      • malloc只会根据自定义类型的空间大小,去开辟对应需求大小的空间
      • new会在malloc功能的基础上,自动调用自定义类型的构造函数对申请的空间上所构造的对象进行初始化【因为此时相当于在所申请的内存区域中构造数据个数个自定义类型的对象,所以在定义的时候便自动调用其构造函数进行初始化】
      • 同理,free只会将malloc所申请的空间进行释放,而delete则会在释放空间前先调用自定义类型的析构函数(以防自定义类型的对象中也向堆区申请了资源,产生内存泄漏问题)进行对象的析构,最后才是对申请的空间进行释放
  • 有了上述的概念,我们便可以解答上述的问题了

➡️这是因为:

  • 之所以能进行初始化,本质其实是:利用了对象自身的构造函数进行初始化

    • new的时候不带括号,代表构造的对象采用的是自身的默认构造函数进行初始化(如果是编译器自动生成的默认构造函数,则对数据不进行处理)
    • new的时候带括号,代表构造的对象采用的是传参构造进行初始化(括号内不传参默认初始化成0)

在这里插入图片描述

针对自定义类型的处理图示:

在这里插入图片描述

  • 上述我们很清楚的就可以看见:

    • 在动态申请内存时:
    • malloc针对自定义类型仅仅是开辟空间,但无初始化
    • 而new则会根据其类型是自定义类型 ,在动态申请出空间的时候,自动调用其默认构造函数进行初始化【如果无默认构造函数,则需要传参进行构造】

在这里插入图片描述

  • 上述我们很清楚的就可以看见:

    • 在释放申请的内存时:
    • free无论是内置类型还是自定义类型,都只会将动态申请的空间进行释放
    • 而delete则会根据其类型是自定义类型 ,在释放动态申请的空间前,先调用自定义类型的析构函数对空间中创建的对象进行资源的释放,最后才对动态申请的空间进行释放

综上:

  • 我们可以看得出来,C++中的动态内存管理(new和delete)相比于C语言是更加严谨的
  • 在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会
  • 所以建议在C++中,无论是内置类型还是自定义类型的申请释放,尽量使用new和delete

🍞三.new和delete的底层原理

💡new和delete的底层原理:

  • newdelete 是用户进行动态内存申请和释放的操作符
  • operator newoperator delete 是系统提供的 全局函数
  • 本质:new 会在底层调用 operator new 全局函数来申请空间,delete 在底层通过 operator delete 全局函数来释放空间

➡️简单来说:

  • new的本质是在malloc的基础上进行封装的,但是new并没有直接调用malloc,而是调用了operator new
  • 同理,delete实质调用的是operator delete
  • operator newoperator delete的作用和malloc和free一样,但operator new会在malloc的功能基础上,增加了抛异常的功能

【即此时我们判断是否成功申请空间,只需要 捕获异常 即可,不需要像malloc一样利用返回值去判断】

特别注意:

  • 这里的operator newoperator delete并不是运算符重载
  • 而是库中提供的全局库函数,相当于这两个名称是函数名

🌰举个例子:

在这里插入图片描述

在这里插入图片描述

  • 综上,我们不难发现:operator new实质也是通过malloc来申请空间的
  • 即调用new的时候其实会转换为调用operator new ➕ 构造函数,从new申请空间失败会抛异常也可以侧面说明new底层调用的是operator new而不是malloc

综上:

  • 抛异常的方式会比malloc的报错方式更加规范,符合C++的特性
  • 这也就是为什么说在C++中建议使用new和delete

🔥 Ⅰ.池化技术的内存管理

💡 operator new与operator delete的类专属重载:

  • 简单来说:就是自定义类型可以重载operator new和operator delete函数,变为这个类中的自己专属的成员函数
  • 即其它类的new都是调用的是全局的operator new函数,而唯独对这两个函数进行重载了的类在new 的时候会调用类中重载过后的operator new函数

🔥重载的意义:

  • 对operator new和operator delete一般多出现在池化技术
  • 池化技术:内存池、进程池、线程池、连接池……【一般多用在一些需要不断申请内存的情况,目的:提高效率
  • 即提前申请并维护好一些内存,当这个类中有申请内存的需求时,就可以直接取提前申请好的内存即可,这样可以有效提高效率

👉目前先简单了解下,后续会结合空间配置器深入理解~


🍞四.定位new

💡定位new:

  • 用于在一个对象在已分配的原始内存空间中调用构造函数初始化自己
  • 使用场景:定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化
  • 简单来说:就是有一块空间(被强转成一个类,相当于此空间就是一个对象),而现在想对这个对象(即这块空间)进行初始化,但在类外面又无法访问到这个对象的成员变量,我们该如何进行初始化呢?
  • 本应该最好的办法就是调用这个对象的构造函数,但构造函数是在对象实例化的时候自动调用的,此时是对这块空间进行强制类型转换,因为空间已经示例化出来了,直接使其变成这个类的对象,是无法调用
  • 那么此时最好的初始化办法就是定位new:从类外面直接调用其构造函数对这个对象(这块空间)进行初始化

🌰举个例子:

1️⃣给对象分配了空间,但未进行初始化

在这里插入图片描述

2️⃣使用定位new在类外调用其构造函数进行初始化

在这里插入图片描述

特别注意:

  • 如果显示调用的构造函数需要传参,我们也可以传参构造
  • 不难发现,定位new的功能就是显示调用构造函数去初始化这块对象空间
  • 定位newoperator new这两条语句的功能组合恰好就是new操作符的功能
  • 同理,以下两语句组合起来的功能等价于使用了delete操作符
//析构函数可以显示调用
pt->~Date(); 
operator delete(pt);

综上:

  • 构造函数是不能在类外显示的去调用的,除了以下两种情况:

    • 对象实例化的时候自动去调用
    • 使用定位new去显示调用

🍞五.内存泄漏的危害

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

[外链图片转存中…(img-ExX5hC4T-1714165033612)]
[外链图片转存中…(img-XcFREixp-1714165033613)]
[外链图片转存中…(img-Zv1vgCgV-1714165033613)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值