1.c/c++中内存区域划分
- 栈:指那些由编译器在需要的时候分配,不需要时自动清除的变量所在的存储区,效率高,分配的内存空间有限,形参和局部变量分配在栈区,栈是向低地址生长的数据结构,是一块连续的内存
- 内存映射段:高效的I/O映射方式,用于装载一个共享的动态内存库。用户可用系统接口创建共享内存,叫做进程间通讯。
- 堆:由程序员控制内存的分配和释放的存储区,是向高地址生长的数据结构,是不连续的存储空间,堆的分配(malloc)和释放(free)有程序员控制
- 数据段:存储全局变量数据和静态变量
- 代码段:可执行代码/只读常量
试着判断下面的变量在内存区域
2.c++内存管理方式
c++是面向对象编程的语言,原先c语言动态开辟内存的方式不适合c++,malloc不方便解决动态申请的自定义类型的初始化问题,所以c++又提出了自己的内存管理方式
1.new
new是c++内置的操作符
对于内置类型new和malloc除了用法没有区别
new内置类型用法:
int* p1 = new int;
//动态申请一个int类型的空间
int* p2 = new int(1);
//动态申请一个int类型的空间并初始化为1
int* p3 = new int[10];
//动态申请十个int类型大小的空间
int* p4 = new int [10]{1,2,3};
//动态申请十个int类型大小的空间,将前三位初始化为1,2,3,后面为初始化为0
new自定义类型用法
对于自定义类型new相当于开辟空间+调用类的默认构造函数
使用new[]操作符,会为s1开辟3个Stack的空间,并调用3次默认构造函数初始化对象。
2.delete
delete是c++内置的操作符
delete内置类型用法:
int* p1 = new int;
delete p1;
int* p2 = new int(1);
delete p2;
int* p3 = new int[10];
delete[] p3;
int* p4 = new int [10]{1,2,3};
delete[] p4;
new申请的空间不能一部分一部分释放,只能整体释放,所以new[]和delete[]要配套使用
delete自定义类型用法:
对于自定义类型delete相当于调用类的析构函数+释放空间
使用delete[]操作符,调用三次类的析构函数,并释放3个Stack类的空间
3.new和delete的实现原理
通过反汇编看到使用new时,首先会调用默认的构造函数初始化对象,然后会调用operator new[]函数,而operator new[]的底层是用malloc函数实现的
同理使用delete[]时,首先会调用operator delete[]函数,而operator delete[]的底层是用free函数实现的,然后调用析构函数
下面的是将Stack的new[]和delete[]的分解
一个小的细节:如果使用new[] 需要调用构造函数,那么在x32平台下new会多开4个字节,这4个字节是用于存储delete[]时析构函数调用的次数
如果new[]开辟空间,new[]会多开辟空间,使用delete[]释放空间,delete[]会在释放时向前多走对于字节然后全部释放空间。
如果new[]开辟空间,使用delete释放空间,delete不会向前走,所以释放空间会导致前面的空间没有释放,导致内存泄漏