【C++初阶】第5课—动态内存管理
文章目录
- 1. 内存分布
- 2. C语言动态内存管理
- 3. C++内存管理方式
- 3.1 new/delete操作内置类型
- 3.2 new和delete操作自定义类型
- 4. operator new和operator delete函数
- 5. new和delete的实现原理
- 6. malloc/free和new/delete的区别
- 7. 定位new表达式(了解即可)
1. 内存分布
先来做一个关于内存的题吧
- 题目
- 答案
2. C语言动态内存管理
- 之前在C语言阶段学了动态管理内存的三种方式malloc、calloc、realloc,回顾一下
3. C++内存管理方式
- C++不仅继承了C语言的内存管理方式,而且还提出了自己的内存管理方式:通过new和delete操作符进行内存管理
3.1 new/delete操作内置类型
- 单个元素的开辟内存和释放内存:new和delete实现
- 多个元素的开辟内存:
new 类型[元素个数]
多个元素的释放:delete[]
3.2 new和delete操作自定义类型
- new和delete对于自定义类型,会分别调用类的默认构造和析构,这是和malloc和free最大的区别
- new和delete对于内置类型不会初始化。但是对于自定义类型是一定会初始化,因为它要调用默认构造,没有默认构造会报错
- 对于类的多参数
4. operator new和operator delete函数
- new和delete是用户通过进行动态申请内存和释放的操作符,operator new和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间
- 从汇编底层指令可以看出,operator new和operator delete是用来实现new和delete的,空间申请失败则会抛出异常,编译器捕获到异常则会进行相应的处理,这里先简单了解下
5. new和delete的实现原理
- 对于内置类型,new和malloc,delete和free基本一样,不同的是:new/delete申请和释放的是单个元素的空间,new[ ]和delete[ ]申请的是连续的空间,而且new在申请空间失败时会抛出异常,malloc则会返回NULL
- 对于自定义类型
- new的原理:
- 调用operator new函数申请空间
- 在申请的空间上执行构造函数,完成对象的构造
- delete的原理:
- 在空间上执行析构函数,完成对象中资源的清理工作
- 调用operator delete函数释放对象的空间
- new[T]的原理:
- **调用operator new[ ]函数,在operator new[ ]中实际调用operator new函数完成N个对象空间的申请 **
- 在申请的空间上执行N次构造函数
- delete[T]的原理:
- 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
- 调用operator delete[ ]释放空间,实际在operator delete[ ]中调用operator delete来释放空间
6. malloc/free和new/delete的区别
- 共同点:都是从堆上申请空间,并且需要用户手动释放
- 不同点:malloc和free是函数,而new和delete是操作符
- malloc申请的空间的同时不能初始化,而new可以
- malloc申请空间时,需要手动计算空间大小并传递,而new只需要给出类型,如果是多个对象,在[ ]中添加对象个数即可
- malloc的返回值是void*,使用时需要进行强转,而new不需要,new后跟的就是空间类型
- malloc申请失败时会返回NULL,而new’失败会抛出异常,捕获异常即可
- 申请自定义类型空间对象时,malloc/free只会开辟空间、释放空间,不会调用构造和析构,而new在申请空间对象时会调用构造函数对对象进行初始化,delete会调用析构函数对空间中的资源进行释放,然后释放该空间
7. 定位new表达式(了解即可)
- 定位new表达式是在已经分配内存的原始空间中调用构造函数来初始化一个对象
- new(place_address)type或者new(place_address)type(initializer-list)
- place_address必须是一个指针,initializer-list是类型的初始化列表
- 定位new表达式一般配合内存池使用,这是因为内存池分配出来的内存没有初始化,如果是自定义类型对象,需要借助new定位表达式进行显式构造函数进行初始化
- 这里简单提两句,内存池呢其实就是从堆中分出一块空间,以供那些频繁向堆申请空间的对象使用,这个后面学习Linux可能细讲