一、内存区域
C语言和C++中,我们常把计算机的内存分为不同的区域,有各自不同的功能:
- 栈区:存放函数的局部变量、参数、返回地址等。
- 堆区:动态开辟(如malloc、new)出的空间是在堆区开辟出来的。
- 全局区(静态区):存放全局变量和静态变量。
- 常量存储区:存放常量,不允许修改。
- 代码区:存放代码编译后的二进制文件,不允许修改,可以读取。
二、C++的内存管理
1. new和delete
C语言的内存管理,主要是由malloc、free一系列函数实现的。这种方式在C++中也可以使用,但相对有些麻烦,所以C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。可以认为,new类似于malloc,delete类似于free。
使用实例:
int* p1 = new int; //申请一个int的空间
int* p2 = new int(1); //申请一个int的空间并初始化为1
int* p3 = new int[10]; //申请10个int的空间
int* p4 = new int[10]{1,2,3,4,5}; //申请10个int的空间,并将前五个初始化为12345
delete p1;
delete p2;
//当动态申请的空间内有多个对象时,要写成delete[]
delete[] p3;
delete[] p4;
2. new和delete的特点
new和delete与malloc和free的共同点是:都是在堆上申请空间,且需要手动释放。不同点是:
- malloc和free是函数,new和delete是操作符。
- malloc申请的空间不会初始化,new申请的空间可以自己进行初始化。
- malloc申请空间需要手动计算空间大小,new只要在后面跟上空间的类型就行,而且new还可以通过[ ]指定对象个数。
- malloc的返回类型是void*,在接受时必须强制类型转换,new不需要。
- malloc申请空间失败时,返回NULL;new申请失败时,会抛异常。
- 申请自定义类型对象时,malloc和free只会开辟空间,而new在申请空间后还会调用构造函数完成对象的初始化,delete在释放空间前会自动调用析构函数完成空间中资源的清理释放。
3. 实现的原理
实际上,new的使用是调用了一个全局函数operator new,这个函数的内部其实还是用malloc实现申请空间的,但当malloc申请失败为NULL时,函数不会报错,而是抛异常。这个概念我们以后学习。
同理,delete的使用也是调用了一个全局函数operator delete,这个函数内部最终也是用free来完成的空间资源释放。
一言以蔽之,内置类型的申请很好理解。
new自定义类型的原理是,调用operator new函数申请空间,并在申请的空间上执行构造函数,完成对象的初始化。
new T[n]的原理是,调用operator new[]函数,在这个函数中调用operator new函数完成对n个对象空间的申请,并在申请的空间上执行n次构造函数。
delete同理。