内存分类
栈区、堆区、动态区、代码段
- 栈区 :用来存储局部变量、函数的形式参数(寄存长期变量)
- 堆区 :动态内存调配
- 动态区 :寄存动态变量、全局变量(程序完结时,才被销毁)
- 代码段 :寄存函数体(类成员函数和全局函数)的二进制代码
int globalvar = 10; //globalvar 存储于动态区(数据段)static int stglobalvar = 10; //stglobalvar 存储于动态区int main(){ static int stcavar = 10; //stcavar 存储于动态区 int locavar = 10; //locavar 局部变量,存储于栈 int num1[10] = { 1,2,3,4 }; //num1 数组存储于栈 char char2[] = "abcd"; //char2 存储于栈; *char2 存储于栈 const char* pchar3 = "abcd"; //pchar3 局部变量指针存储于栈中,*pchar3 存储于代码段中(常量区) int* ptr = (int*)malloc(sizeof(int) * 4); //ptr 局部变量指针存储于栈中; *ptr开拓的空间,存储于堆中 free(ptr);}
内存透露
- 什么是内存透露:因为某种原因导致程序未能开释不再应用的内存。
- 内存透露不是指物理上的内存隐没,而是指失去了对某段内存的控制权(指针失落)
C++动静申请内存new
- C++语法兼容C语言,所以C语言的malloc和realloc等都能够应用。
- C++语法还有新的办法能够动静申请内存空间——new和delete
- 留神:malloc开拓的空间只能free,new开拓的空间只能delete。
int main(){ int* ptr1 = (int*)malloc(sizeof(int) * 4); int* ptr2 = new int[10]; //开拓多个空间时,应用中括号 free(ptr1); delete[] ptr2; int* ptr3 = (int*)malloc(sizeof(int)); int* ptr4 = new int; //开拓单个空间时 free(ptr3); delete ptr4;}
malloc和new的区别
- malloc和new在申请根本类型的空间时,都是一样的,没有区别。
区别:
- new在申请自定义类型时,会开拓空间,并调用构造函数进行初始化。
- malloc只是开拓空间,而不会进行初始化。
- delete是先析构函数清理,再开释空间。
- free只是开释空间。
- malloc开拓空间失败后返回NULL,而new开拓空间失败会抛异样。
- 32位零碎下,new和malloc最多能申请2G内存,想申请更大内存能够换成64位。
struct List{ List* _pre; List* _next; int _val; List(int val = 0) //构造函数 :_pre(nullptr) ,_next(nullptr) ,_val(val) {}};int main(){ struct List* n1 = (struct List*)malloc(sizeof(struct List)); List* n2 = new List;}
operator new和operator delete函数
- new和delete是零碎提供的操作符,而operator new和 operator delete是零碎提供的全局函数
- 操作符new的底层是通过调用operator new来申请空间的。
操作符delete的底层是通过调用 operator delete来开释空间的。
- new 相当于 operator new + 构造函数
- delete相当于 析构函数 + operator delete
- operator new 相当于 malloc + 失败抛异样机制
- operator delete 相当于 free
- operator new 和 operator delete 在性能上和 malloc 和free 雷同
- 都只是开拓空间而不会调用构造函数进行初始化。
operator new 和 malloc 的区别
次要区别是:当开拓空间失败后,解决办法不同。
- operator new 失败后是抛异样
- malloc 失败后是返回 NULL。
- 当 try 中运行出现异常后,会立马跳转到 catch 中。
int main(){ struct List* n1 = (struct List*)malloc(0x7fffffff); if (n1 == NULL) //malloc失败返回 NULL { cout << "malloc 失败" << endl; } try //尝试运行下列代码 { List* n3 = (struct List*)operator new(0x7fffffff); } catch (const std::exception&e) //try运行失败后,捕捉异样 { cout << e.what() << endl; }}
定位new(初始化已开拓的空间)
- 定位new是用来在曾经开拓了的空间中,通过调用构造函数来对其进行初始化。
int main(){ List* n1 = (List*)malloc(sizeof(List)); //开拓空间,但未初始化 new(n1)List; //定位new 调用构造函数,初始化对象 n //等价于operator new List* n2 = (List*)operator new(sizeof(List)); new(n2)List; //等价于 delete n2->~List(); //调用析构函数,析构函数是能够显示调用的,然而构造函数不能。 operator delete(n2);}