03.C++内存管理笔记

这篇具有很好参考价值的文章主要介绍了03.C++内存管理笔记。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、C/C++内存分布

03.C++内存管理笔记,笔记

①内存分那么多区的原因:不同的数据,有不同的存储需求,各区域满足了不同的需求。

②存放:

临时变量等临时用的变量:栈区;

动态申请的变量:堆区;

全局变量和静态变量等整个程序期间都使用的变量:数据段;

常量、可执行代码等只读数据:代码段;

2、C语言中动态内存管理方式:malloc/calloc/realloc/free

3、C++内存管理方式

C语言的内存管理方式在C++中依然可以使用但是有些情况不方便,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。

①new/delete操作内置类型

1°new操作符

动态开辟一个整型:

int* p=new int;

动态开辟一个整型同时赋个初值:

int* p=new int(3);

动态开辟多个整型:

int* p=new int[10];

动态开辟多个整型同时赋值:

int* p=new int[10]{1,2,3};

2°delete操作符

释放申请的一个空间:

delete p;

释放申请的多个空间:

delete[] p;

★new和delete,new[]和delete[]匹配起来使用;

★对于内置类型,malloc和new除了用法上的区别,没有别的区别;

②new/delete操作自定义类型

C语言的动态管理对于自定义类型是不好解决初始化的,所以必须要使用C++提供的new和delete

1°new操作符

动态开辟一个自定义类型:

A* p=new A;       //A是一个自定义的类

动态开辟一个自定义类型同时赋初值:

A* p=new A(1);       //自定义类型有传一个整型的构造函数

动态开辟多个自定义类型:

A* p=new A[3];          //开辟三个自定义类型的对象

动态开辟多个自定义类型同时赋初值:

A* p=new A[3]{1,2,3};         //隐式类型转换赋初值
A* p=new A[3]{aa1,aa2,aa3};     //利用已有的对象赋初值
A* p=new A[3]{A(1),A(2),A(3)};           //用匿名对象赋初值

★new的本质:开空间+调用构造函数初始化

2°delete 

释放申请的一个空间:

delete p;

释放申请的多个空间:

delete[] p;

★delete的本质:调用析构函数+释放空间

③new失败

1°new失败的话会抛出异常,但是异常需要捕获;

2°cout打印char*类型的数据的时候,默认打印的是字符串类型,想要打印地址可以使用printf或者前面加(void*)强制类型转换

4、operator new与operator delete函数

①new和delete是用户进行动态内存申请和释放的操作符,operator new和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层调用operator delete全局函数来释放空间。(这两个函数不是对new和delete的重载)

②operator new和operator delete封装的malloc和free。malloc失败了返回0,operator new失败了抛异常,这样更符合面向对象的特性。operator delete是为了和operator new配对。

5、new和delete的实现原理

①new和delete是操作符,运行时new直接转换成汇编指令,汇编指令中调用了operator new之后调用构造函数,delete直接转换成汇编指令,汇编指令中调用了析构函数之后,调用operator delete。

即:

new的原理:调用operator new函数申请空间

                     在申请的空间上执行构造函数,完成对象的构造

delete的原理:在空间上调用析构函数,完成对对象资源的清理工作

                        调用operator delete函数完成对象空间的释放

new[]的原理:调用1次operator new[]函数申请N个对象的空间   

                       在申请的空间上执行N次构造函数,完成对象的构造

                       ★开空间时会在空间的头部多开四个字节的空间。

                       ★多开四个字节空间是为了告诉delete[]调用析构函数时调用几次

delete[]的原理:在空间上调用N次析构函数,完成对对象资源的清理工作

                          调用1次operator delete函数完成对象空间的释放

                          ★释放空间时会向前减四个字节开始释放空间

▲如果使用new[]申请空间,使用delete释放空间,逻辑上一定是错的,但是可是报错,可能不报错。报错是因为,new[]申请空间时在空间的前面多申请了四个字节的空间,delete释放是没有从四个字节前开始释放,相当于从中间开始释放的,这是肯定会报错的。不报错的话,就是因为你的类没有显式的写析构函数,并且你的成员变量都是内置类型,new[]申请空间时前面没有多申请前面四个字节的空间,所以使用delete释放也是可以的,但是这属于编译器的优化,是编译器做的,不一样的编译器不一定做法相同。所以写的时候一定要注意匹配的问题。

6、定位new表达式(placemen-new)

①构造函数和析构函数都可以显式调用,析构函数像调用普通函数一样直接调用就好了,而构造函数像普通函数一样直接调用会报错,需要使用定位new来进行显式调用。

②定位new显式调用构造函数的主要场景:

一般定位new都是和内存池一起配合使用的,我们频繁去堆开辟一小块空间是效率非常低的,所以有了内存池的概念,内存池就是一次在堆中申请一块比较大的空间,然后我们创建对象时先去内存池看看空间够不够,空间不够就去堆中开辟,空间够就直接使用内存池内的空间,而内存池的空间是以前开辟的,所以是未初始化的,我们想要初始化就需要使用定位new来显式调用构造函数。

③使用格式:

new(place_address) type 或者new(place_address) type (Initializer_list)

place_address:必须是一个指针

initializer_list:是类型的初始化列表文章来源地址https://www.toymoban.com/news/detail-819416.html

到了这里,关于03.C++内存管理笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++内存管理机制(侯捷)笔记4(完结)

    本文是学习笔记,仅供个人学习使用。如有侵权,请联系删除。 参考链接 Youtube: 侯捷-C++内存管理机制 Github课程视频、PPT和源代码: https://github.com/ZachL1/Bilibili-plus 下面是第四讲和第五讲的笔记。 第四讲:loki库的allocator 第五讲:other issues,主要介绍GNU C++提供的其他分配器的

    2024年02月02日
    浏览(41)
  • 操作系统-笔记-第三章-内存管理

    一、第一章——操作系统的概念 二、第二章——【进程】 二、第二章——【线程】​编辑 二、第二章——【进程调度】 二、第二章——【进程同步与互斥】 二、第二章——【锁】 三、第三章——内存管理 四、第四章——文件管理 五、第五章——输入输出管理 ​​​​​

    2024年02月11日
    浏览(70)
  • 《C++高级编程》读书笔记(七:内存管理)

    1、参考引用 C++高级编程(第4版,C++17标准)马克·葛瑞格尔 2、建议先看《21天学通C++》 这本书入门,笔记链接如下 21天学通C++读书笔记(文章链接汇总) 1. 使用动态内存 1.1 如何描绘内存 在本书中,内存单元表示为一个带有标签的框,该标签表示这个内存对应的变量名,方

    2024年02月08日
    浏览(87)
  • (学习笔记-内存管理)如何避免预读失效和缓存污染的问题?

    传统的LRU算法存在这两个问题: 预读失效 导致的缓存命中率下降 缓存污染 导致的缓存命中率下降 Redis的缓存淘汰算法是通过 实现LFU算法 来避免 [缓存污染] 而导致缓存命中率下降的问题(redis 没有预读机制) Mysql 和 Linux操作系统是通过 改进LRU算法 来避免 [预读失效和缓存

    2024年02月14日
    浏览(47)
  • Objective-C学习笔记(内存管理、property参数)4.9

    1.引用计数器retainCount: 每个对象都有这个属性,默认值为1,记录当前对象有多少人用。    为对象发送一条retain/release消息,对象的引用计数器加/减1,为对象发一条retainCount,得到对象的引用计数器值,当计数器为0时自动调用对象的dealloc方法。    手动发送消息:-(id)perf

    2024年04月13日
    浏览(45)
  • 【操作系统】24王道考研笔记——第三章 内存管理

    1.基本概念 2.覆盖与交换 覆盖技术: 交换技术: 总结: 3.连续分配管理方式 单一连续分配 固定分区分配 动态分区分配 动态分区分配算法: 总结: 4.基本分页存储管理 定义: 页表: 地址转换的实现: 子问题: 逻辑地址结构: 总结: 5.基本地址变换机构 流程: 原理:

    2024年02月11日
    浏览(66)
  • 【嵌入式环境下linux内核及驱动学习笔记-(10-内核内存管理)】

    对于包含MMU(内存管理单元)的处理器而言,linux系统以虚拟内存的方式为每个进程分配最大4GB的内存。这真的4GB的内存空间被分为两个部分–用户空间 与 内核空间。用户空间地地址分布为0~3GB,剩下的3 ~ 4GB 为内核空间。如下图。 用户进程通常只能访问用户空间的虚拟地址

    2024年02月11日
    浏览(58)
  • 【操作系统笔记04】操作系统之内存管理方式(分页、分段、段页式)、虚拟存储技术、页面置换算法

    这篇文章,主要介绍操作系统之内存管理方式(分页、分段、段页式)、虚拟存储技术、页面置换算法。 目录 一、操作系统 1.1、基地址变换机构 1.2、具有快表的地址变换机构

    2023年04月21日
    浏览(45)
  • 【Qt】QJsonArray清空,释放内存【2023.07.03】

      C++标准容器的清空是调用的swap函数,Qt的还真不清楚。故写了个Demo进行测试。经测试直接等于号赋空对象即可。

    2024年02月12日
    浏览(49)
  • 【JUC进阶】03. Java对象头和内存布局

    为了后面更好的学习锁优化以及运作过程,需要我们对HotSpot虚拟机的Java对象内存布局有一定的了解,也作为技术储备。 在HotSpot虚拟机中,对象在堆内存中存储的布局可以划分为三个部分:对象头(Header)、实例数据(Instance Data)、对齐填充(Padding)。 而数组对象和普通对

    2024年02月10日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包