内存分布
C++中的内存区域主要有以下5种
-
栈(堆栈):存放
非静态局部变量
/函数参数
/函数返回值
等等,栈是向下增长的【地址越高
越先被使用】。栈区内存的开辟和销毁由系统自动执行 -
堆:用于程序运行时动态内存分配,由程序员申请和释放内存,堆是向上增长的【地址越
低
越先被使用】。 -
内存映射段:是高效的I/O映射方式,用于
装载一个共享的动态内存库
。用户可使用系统接口创建共享共享内存,做进程间通信。 -
数据段(全局区):存储
全局数据
和静态数据
。 -
代码段(常量区):存放
可执行的代码
/只读常量
。
C++动态内存管理
动态内存申请
动态内存申请,申请的是堆区
的内存
申请一个类型大小的空间
不初始化申请的空间语法:
T* p=new T
(T代指类型,p可以是任意合法标识符)
例
int* p = new int;
即可申请1个int类型大小的未初始化的空间
初始化申请内置类型的空间语法:
T* p=new T(要初始化的值)
(T代指类型,p可以是任意合法标识符)
例
int* p = new int(200);
即可申请1个int类型大小的初始化为200的空间
调用指定构造函数申请自定义类型的空间语法:
T* p=new T(传给自定义类型的构造函数的参数)
(T代指类型,p可以是任意合法标识符)
申请连续多个类型大小的空间
不初始化申请的空间语法:
T* p=new T【n】
(T代指类型,p可以是任意合法标识符,n是要申请的连续的类型空间的个数)
例
int* p = new int[12];
即可申请连续12个int类型大小未初始化的空间
初始化申请内置类型的空间语法:
T* p=new T【n】{初始值1,初始值2,……}
(T代指类型,p可以是任意合法标识符,n是要申请的连续的类型空间的个数)
例
int* p = new int[12] {1,2,3,4,5,6};
即可申请连续12个int类型大小的前6个int空间的值为1,2,3,4,5,6,后6个int空间值为0的空间
调用指定构造函数申请自定义类型的空间语法:
T* p=new T【n】{{传给第一个自定义类型的构造函数的参数},{传给第二个}
(T代指类型,p可以是任意合法标识符,n是要申请的连续的类型空间的个数)
例
动态内存释放
释放一个类型大小的空间
语法:
delete p
(p是存放了动态内存申请的空间的首地址的指针)
例
int* p = new int;delete p;
释放连续多个类型大小的空间
语法:
delete[] p
(p是存放了动态内存申请的空间的首地址的指针)
例
int* p = new int[12];delete[] p;
operator new和operator delete
这两个都是库里实现好的全局函数
operator new是C语言的malloc
的封装函数,主要封装了malloc失败时不在返回NULL而是抛异常
即申请空间本质上还是使用malloc
operator delete是C语言的free
的封装函数
即释放空间本质上还是使用free
new和delete以及new T[]和delete[]实现原理
new
- 先调用operator new函数申请空间
- 如果是
自定义类型
就再调用它的构造函数
delete
- 如果是
自定义类型
就调用它的析构函数 - 调用operator delete 释放申请的空间
new T[n]
- 调用operator new申请连续的n个类型大小的空间
- 如果是
自定义类型
就再调用n次
它的构造函数
delete[]
- 如果是
自定义类型
就调用n次
它的析构函数 - 调用operator delete释放连续的n个类型大小的空间
new的delete与malloc和free的区别
-
malloc和free是
函数
,new和delete是操作符
-
malloc申请的空间
不能初始化
,new可以初始化 -
malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常
-
申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理
-
malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型