C/C++内存管理
目录
1. 首先做一道题
2. C/C++的内存管理方式
2.1 概念
2.2 malloc,new的区别,free,delete的区别
2.3 抛异常的捕获(后面会讲)
2.4 operator new与operator delete函数
2.5 operator new[]
2.6 new delete不匹配问题
3. new和delete 的总结
3.1 内置类型
3.2 自定义类型
4. 池化技术&&定位new表达式(placement-new)
C语言总结在这常见八大排序在这
作者和朋友建立的社区:非科班转码社区-CSDN社区云💖💛💙
期待hxd的支持哈🎉 🎉 🎉
最后是打鸡血环节:你只管努力,剩下的交给天意🚀 🚀 🚀
1. 首先做一道题
测试一下自己哈,实在不懂可以评论区或者私聊哈
答案(做的时候没反应过来全局变量是静态区哈哈)
【说明】
1. 栈 又叫堆栈,非静态局部变量 / 函数参数 / 返回值等等,栈是向下增长的。 2. 内存映射段 是高效的 I/O 映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信。(Linux 课程如果没学到这块,现在只需要了解一下) 3. 堆 用于程序运行时动态内存分配,堆是可以上增长的。 4. 数据段 -- 存储全局数据和静态数据。 5. 代码段 -- 可执行的代码 / 只读常量。
2. C/C++的内存管理方式
2.1 概念
我们知道C是malloc/calloc/realloc。
C 语言内存管理方式在 C++ 中可以继续使用,但有些地方就无能为力而且使用起来比较麻烦,因此 C++ 又提出了自己的内存管理方式:通过 new 和 delete 操作符进行动态内存管理 。 例如:
C++11:
注意:申请和释放单个元素的空间,使用 new 和 delete 操作符,申请和释放连续的空间,使用 new[] 和 delete[]
2.2 malloc,new的区别,free,delete的区别
在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会。其他的没有本质的区别。
2.3 抛异常的捕获(后面会讲)
也就是这个原因,所以new不用想malloc一样去判断
2.4 operator new与operator delete函数
首先operator new operator delete是两个库函数,不是new delete的重载(malloc free是函数 new delete 是操作符),这也是很容易引起误会的地方。
new 和 delete 是用户进行 动态内存申请和释放的操作符 , operator new 和 operator delete 是系统提供的 全局函数 , new 在底层调用 operator new 全局函数来申请空间, delete 在底层通过 operator delete 全局 函数来释放空间。
operator new 的本质是封装了malloc,但是失败不返回空,是抛异常(可以去看对应的源码)
operator delete 本质也是封装的free(为了和operator new 配对)operator new && malloc
那还不如 new 好用
所以operator new 是没有直接价值的,但是有间接价值:
call operator new call 构造函数new的本质其实是call operator new 和 call Stack的构造函数
2.5 operator new[]
不过其实operator new[] 也是封装的operator new
2.6 new delete不匹配问题
虽然都没有正确匹配使用delete,但是上面不报错下面报错,简单提一下原因(不全),上面还是相当于malloc 然后 free 所以没问题,下面是相当于new10 只delete 1次,不过还有很多底层机制的问题
3. new和delete 的总结
3.1 内置类型
如果申请的是内置类型的空间, new 和 malloc , delete 和 free 基本类似,不同的地方是: new/delete 申请和释放的是单个元素的空间,new[] 和 delete[] 申请的是连续空间,而且 new 在申请空间失败时会抛异常, malloc 会返回 NULL 。
3.2 自定义类型
new 的原理 1. 调用 operator new 函数申请空间 2. 在申请的空间上执行构造函数,完成对象的构造 delete 的原理 1. 在空间上执行析构函数,完成对象中资源的清理工作 2. 调用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 来释放空间
4. 池化技术&&定位new表达式(placement-new)
//以下内容后面会详细说,先了解
在连续多次申请空间的时候,效率是低下的
池化技术可以解决(内存池,进程池)
就是开辟一块大的空间然后以后去内存池申请和释放空间,可以这么理解,内存池离我们进,速度快我们上面开始提到了,new会去调用operator new,但是这是全局的(库里面的),现在我们去重载一个operator new,就会去调用这个专属的(内存池)
我们new的是Listnode 所以我们就在Listnode里面写一个operator new / delete意义就是提高效率
假设现在我们有了一块空间并且没有初始化,我们如何 显示调用构造函数去初始化呢(平时都是编译器默认调用的,我们自己是不能直接调用的)? 定位new表达式: 定位 new 表达式是在 已分配的原始内存空间中调用构造函数初始化一个对象 。 使用格式: new (place_address) type 或者 new (place_address) type(initializer-list) place_address 必须是一个指针, initializer-list 是类型的初始化列表 使用场景: 定位 new 表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new 的定义表达式进行显示调构造函数进行初始化。
意义:内存池切出来的内存就要用定位new
最后的最后,创作不易,希望读者三连支持💖
赠人玫瑰,手有余香💖