【本节目标】
1. C/C++
内存分布
2. C
语言中动态内存管理方式
3. C++
中动态内存管理
4. operator new
与
operator delete
函数
5. new
和
delete
的实现原理
1. C/C++内存分布
【说明】
- 栈又叫堆栈--非静态局部变量/函数参数/返回值等等,栈是向下增长的。
- 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信。
- 堆用于程序运行时动态内存分配,堆是可以上增长的。
- 数据段--存储全局数据和静态数据。
- 代码段--可执行的代码/只读常量。
2. C语言中动态内存管理方式:malloc/calloc/realloc/free
malloc 开辟堆内存
calloc 开辟堆内存并初始化为0
realloc 追加堆内存
free 释放堆内存
3. C++内存管理方式
C 语言内存管理方式在 C++ 中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此 C++ 又提出了自己的内存管理方式:通过 new 和 delete 操作符进行动态内存管理 。3.1 new/delete 操作内置类型注意:申请和释放单个元素的空间,使用 new 和 delete 操作符,申请和释放连续的空间,使用 new[] 和 delete[] ,注意:匹配起来使用。3.2 new 和 delete 操作自定义类型class A { public: A(int a = 0) :_a(a) { cout << "A():" << this << endl; } ~A() { cout << "~A():" << this << endl; } private: int _a; }; int main() { /*new/delete 和 malloc/free最大区别是 new/delete对于 【自定义类型】除了开空间还会调用构造函数和析构函数*/ A* p1 = (A*)malloc(sizeof(A)); A* p2 = new A(1); free(p1); delete p2; //内置类型是几乎是一样的 int* p3 = (int*)malloc(sizeof(int));//C int* p4 = new int; free(p3); delete p4; A* p5 = (A*)malloc(sizeof(A) * 10); A* p6 = new A[5]; free(p5); delete p6; return 0; }
注意:在申请自定义类型的空间时, new会调用构造函数,delete会调用析构函数 ,而 malloc 与 free 不会 。
4. operator new与operator delete函数
4.1 operator new 与 operator delete 函数(区别于malloc返回空指针 operator new 会 抛异常)new 和 delete 是用户进行 动态内存申请和释放的操作符 , operator new 和 operator delete 是系统提供的 全局函数 , new 在底层调用 operator new 全局函数来申请空间, delete 在底层通过 operator delete 全局函数来释放空间。operator new 实际也是通过 malloc 来申请空间 ,如果 malloc 申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。operator delete 最终是通过 free 来释放空间的 。
5. new和delete的实现原理
5.1 内置类型如果申请的是内置类型的空间, new 和 malloc , delete 和 free 基本类似,不同的地方是: new/delete 申请和释放的是单个元素的空间,new[] 和 delete[] 申请的是连续空间,而且 new在申请空间失败时会抛异常, malloc会返回NULL。5.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 来释放空间