对于C语言和C++而言,它们的内存分布都是一样的
而内存是编写程序时必须要关心的点,一定要防止内存过载 内存泄漏等问题
一旦内存出现问题程序就会直接崩溃,甚至严重的还会导致系统死机等
C/C++的内存分布
C/C++的内存分布可以简易的划分为以下图示
不同的数据会存放在对应的空间中
- 栈又叫堆栈–非静态局部变量/函数参数/返回值等等,栈是向下增长的
- 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库
- 堆存放动态开辟的内存分配,堆是可以上增长的。
- 数据段–存储全局数据和静态数据
- 代码段–可执行的代码/只读常量
C++的动态内存管理
对于C语言想要开辟一块内存可以用到 malloc、calloc、realloc这三个函数,而对于C++也有自己的开辟内存方式-- new负责开辟空间 delete负责释放空间。前者是C语言中的函数,而后者是C++中的操作符
new、delete的使用
int main() { //开辟一块int类型的空间并初始化为10 int* a = new int(10); //开辟一块char类型的空间 int* b = new int; //开辟一块连续的有10个double类型的空间 double* c = new double[10]; //如果申请的空间只有一个时 delete a; a = nullptr; delete b; b = nullptr; //申请了连续空间时 delete[] c; c = nullptr; return 0; }
new/delete和malloc/free使用上的区别
- malloc申请出来的空间不可以进行初始化,但new可以
- malloc的返回值为void* 因此需要强转为指定类型,而new不需要
- malloc开辟空间时需要计算出空间的字节大小,而new不用它会自动识别类型只需要在[]里输入个数即可
- malloc开辟失败会返回NULL,new会捕捉异常
- 申请自定义类型空间时,malloc/free不会调用构造和析构函数,new会调用构造函数并且在delete释放空间前会调用析构函数清理资源
new和delete的底层原理
其实这两个的底层也是用malloc和free实现的,在C++中有两个全局函数 operator new、operator delete。这两个全局函数使用malloc和free定义的。在用户调用new和delete,它们会分别调用这两个全局函数。
new调用operator new函数申请空间,并执行对应类型的构造函数完成对象的初始化
delete首先会执行对应类型的析构函数,然后再调用operator delete释放空间
new T[N] 这种连续的开辟空间实际上会调用N次构造函数
delete[] 也就是会调用N次析构函数,不需要指明N
了解内存泄漏
内存泄漏是一种经常会出现的情况,如果是长期运行的程序出现了内存泄漏就会慢慢的导致系统卡死。
内存泄露可能出现的情况:
- 堆内存泄露也就是当用户开辟了空间后没有释放掉,那这部分空间就会一直无法被操作系统收回也就无法再次使用,长期积累就会导致内存空间不足
- 野指针的问题也会导致空间找不回来系统收不回去
因此在写程序时一定要额外的注意内存问题,只要有开辟了空间就一定要记得使用完之后释放。