零、前言
本章将学习掌握C++的内存管理,以及明白C和C++内存管理的相同与不同
一、C/C++内存分布
- 示例:
int globalVar = 1; static int staticGlobalVar = 1; void Test() { static int staticVar = 1; int localVar = 1; int num1[10] = { 1, 2, 3, 4 }; char char2[] = "abcd"; const char* pChar3 = "abcd"; int* ptr1 = (int*)malloc(sizeof(int) * 4); int* ptr2 = (int*)calloc(4, sizeof(int)); int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4); free(ptr1); free(ptr3); }
- 变量储存分布:
说明:
栈又叫堆栈,非静态局部变量/函数参数/返回值等等,栈是向下增长的
内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库,用户可使用系统接口创建共享共享内存,做进程间通信
堆用于程序运行时动态内存分配,堆是可以上增长的
数据段–存储全局数据和静态数据
代码段–可执行的代码/只读常量 (指令以及常量)
二、C语言动态内存管理
注:具体相关知识在–>C语言内存管理
- malloc/calloc/realloc/和free:
示例:
void Test() { int* p1 = (int*)malloc(sizeof(int)); int* p2 = (int*)calloc(4, sizeof(int)); int* p3 = (int*)realloc(p2, sizeof(int) * 10); // 1.malloc/calloc/realloc的区别是什么? // malloc在堆上开辟对应字节的空间,不初始化 // calloc开辟对应字节的空间并初始化为0 // realloc调整应经动态开辟空间的大小,可以扩容也可以缩小 free(p1);//申请动态开辟空间需要进行释放,否则可能造成内存泄漏 //realloc扩容有两种情形,一是在原空间上进行扩(后面有足够大的空间) //二是另找一足够大的空间进行开辟,并将原空间内容拷贝(原空间后没有足够大的空间),且自动释放原空间 //所以此处只需要释放p3就行了 free(p3); }
三、C++动态内存管理
- 概念:
C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理
- new/delete操作内置类型:
void Test() { // 动态申请一个int类型的空间 int* ptr4 = new int; // 动态申请一个int类型的空间并初始化为3 int* ptr5 = new int(3); // 动态申请3个int类型的空间 int* ptr6 = new int[3]; int* ptr7 = new int[3]{1,2,3};//开辟并初始化 delete ptr4; delete ptr5; delete[] ptr6; }
- 注意:
申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[],一定要匹配使用,否则可能出错
- new和delete操作自定义类型:
示例:
class Test { public: Test() : _data(0) { cout << "Test():" << this << endl; } ~Test() { cout << "~Test():" << this << endl; } private: int _data; }; void Test2() { // 申请单个Test类型的空间 Test* p1 = (Test*)malloc(sizeof(Test)); free(p1); // 申请10个Test类型的空间 Test* p2 = (Test*)malloc(sizeof(Test) * 10); free(p2); } void Test3() { // 申请单个Test类型的对象 Test* p1 = new Test; delete p1; // 申请10个Test类型的对象 Test* p2 = new Test[10]; delete[] p2; }
- 注意:
在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会