内存分配方式
在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。
栈,在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。
自由存储区,就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。
全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。
常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改。
示例一
1 void func() 2 { 3 int* p=new int[5]; 4 delete []p; 5 }
说明:func()与栈有关,new与堆有关。该语句表示在栈内存中存放了一个指向一块堆内存的指针p。在程序会先确定在堆中分配内存的大小,然后调用operator new分配内存,然后返回这块内存的首地址,放入栈中。
堆与栈的区别
| 区别 | 栈 | 堆 |
| 管理方式 | 编译器自动管理 | 程序员手动管理 |
| 空间大小 | 有限制 | 一般无限制 |
| 生长方向 | 向着内存地址减小的方向增长 | 向着内存地址增加的方向 |
| 分配方式 |
局部变量是由编译器静态分配; 动态分配是由alloca函数进行,最后由编译器自动释放; |
动态分配 |
| 效率 |
高。栈是机器系统提供的数据结构,计算机在底层对栈提供支持, 分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行 |
低。堆则是C/C++函数库提供的,它的机制是很复杂的,为了分配一块内存, 库函数会按照一定的算法在堆内存中搜索可用的足够大小的空间, |
| 碎片问题 |
先进后出,不产生碎片 |
频繁的new/delete势必会造成内存空间的不连续,造成大量碎片 |
内存分配规则
【规则1】用malloc或new申请内存之后,应该立即检查指针值是否为NULL。防止使用指针值为NULL的内存。
【规则2】不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。
【规则3】避免数组或指针的下标越界,特别要当心发生“多1”或者“少1”操作。
【规则4】动态内存的申请与释放必须配对,防止内存泄漏。
【规则5】用free或delete释放了内存之后,立即将指针设置为NULL,防止产生“野指针”。
“野指针”不是NULL指针,是指向“垃圾”内存的指针。产生原因:指针变量没有被初始化;指针p被free或者delete之后,没有置为NULL;指针操作超越了变量的作用域范围。
malloc/free和new/delete的区别
malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。
对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。
因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。
malloc/free和new/delete用法
//malloc/free原型 void * malloc(size_t size); void free(void * memblock); int *p1 = (int*) malloc(sizeof(int)*length); int *p2 = new int[length]; free(p1); delete []p2;
说明:
指针p1的类型以及它所指的内存的容量事先都是知道的,语句free(p)能正确地释放内存;
new内置了sizeof、类型转换和类型安全检查功能。对于非内部数据类型的对象而言,new在创建动态对象的同时完成了初始化工作。如果对象有多个构造函数,那么new的语句也可以有多种形式。
浙公网安备 33010602011771号