如题所述
第1个回答 2022-10-26
堆记忆体是区别于栈区、全局数据区和代码区的另一个记忆体区域。堆允许程式在运行时动态地申请某个大小的记忆体空间。
基本介绍 中文名 :堆记忆体 外文名 :heap 区别 :于栈区 类型 :软体 获得堆记忆体 :malloc() 比较,分配,重要函式,记忆体方式,malloc函式,new运算符,典型示例, 比较 在学习C程式设计语言时,会遇到两个很相似的术语:堆记忆体和栈记忆体。这两个术语虽然只有一字之差,但是所表达的意义还是有差别的,堆记忆体和栈记忆体的区别可以用如下的比喻来看出:使用堆记忆体就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。使用栈记忆体就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。作业系统中所说的堆记忆体和栈记忆体,在操作上有上述的特点,这里的堆记忆体实际上指的就是(满足堆记忆体性质的)优先伫列的一种数据结构,第1个元素有最高的优先权;栈记忆体实际上就是满足先进后出的性质的数学或数据结构。 堆记忆体和栈记忆体 分配 在标准C语言上,使用malloc等记忆体分配函式获取记忆体即是从堆中分配记忆体,而在一个函式体中例如定义一个数组之类的操作是从栈中分配记忆体。从堆中分配的记忆体需要程式设计师手动释放,如果不释放,而系统记忆体管理器又不自动回收这些堆记忆体的话(实现这一项功能的系统很少),那就一直被占用。如果一直申请堆记忆体,而不释放,记忆体会越来越少,很明显的结果是系统变慢或者申请不到新的堆记忆体。而过度的申请堆记忆体(可以试试在函式中申请一个1G的数组!),会导致堆被压爆,结果是灾难性的。 动态分配堆记忆体 我们掌握堆记忆体的权柄就是返回的指针,一旦丢掉了指针,便无法在我们视野内释放它。这便是记忆体泄露。而如果在函式中申请一个数组,在函式体外调用使用这块堆记忆体,结果将无法预测。 我们知道在c/c++ 中定义的数组大小必需要事先定义好,他们通常是分配在静态记忆体空间或者是在栈记忆体空间内的,但是在实际工作中,我们有时候却需要动态的为数组分配大小,这时就要用到堆记忆体分配的概念。在堆记忆体分配时首先应该知道作业系统有一个记录空闲记忆体地址的炼表,当系统收到程式的申请时,会遍历该炼表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点炼表中删除,并将该结点的空间分配给程式,另外,对于大多数系统,会在这块记忆体空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本记忆体空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲炼表中。堆记忆体是向高地址扩展的数据结构,是不连续的记忆体区域。这是由于系统是用炼表来存储的空闲记忆体地址的,自然是不连续的,而炼表的遍历方向是由低地址向高地址。堆记忆体的大小受限于计算机系统中有效的虚拟记忆体。由此可见,堆记忆体获得的空间比较灵活,也比较大。堆记忆体是由new分配的记忆体,一般速度比较慢,而且容易产生记忆体碎片,不过用起来最方便.另外,在WINDOWS下,最好的方式是用VirtualAlloc分配记忆体,它直接在进程的地址空间中保留一快记忆体,虽然用起来最不方便。但是速度快,也最灵活。 重要函式 获得堆记忆体:malloc() 动态分配堆记忆体 原型:extern void *malloc( unsigned int num_bytes); 功能:分配长度为num_bytes位元组的记忆体块 说明:如果分配成功则返回指向被分配记忆体的指针,否则返回空指针NULL。当记忆体不再使用时,应使用free()函式将记忆体块释放。 malloc的语法是:指针名=(数据类型*)malloc(长度),(数据类型*)表示指针. 记忆体方式 malloc函式 例: int *p;p = (int*)malloc(sizeof(int)); 使用malloc函式分配记忆体时,返回值要经过类型转换才可赋予一个指针变数。该函式如分配记忆体成功,则返回其始地址,否则返回NULL。头档案为#include<stdlib.h>。 new运算符 例: int *p,*q;p = new int;申请分配一个int型记忆体空间p = new int(10);申请一个int型空间存放10q = new int[10];申请分配10个int型的记忆体空间 new分配记忆体时不需要类型转换。用new申请的空间必须要用delete释放。而且指针值不能改变。形式有:delete指针变数名(可释放一个记忆体单元)、delete[]指针变数名(可释放若干个记忆体单元)。 典型示例 例1: #include<iostream>using namespace std;main(){int array_size;元素个数int *array;用于动态开辟数组的指针变数cin>>array_size;array=(int*)malloc(array_size*sizeof(int));/*利用malloc在堆记忆体中开辟记忆体空间,它的大小是元素的个数乘以该数据类型的长度 */for(int i=0;i<array_size;i++)array[i]=i;输入数组for( i=0;i<array_size;i++)cout<<array[i]<<",";以逗号间距输出数组cout<<endl;换行free(array);利用free释放动态开辟的堆记忆体空间cin.get();按任意键结束return 1;返回值}VC6.0通过 网页格式符 请不要直接复制贴上本段编译 这里要特别注意个地方就是: array=(int*)malloc(array_size*sizeof(int));malloc() 函式原形本身是void*malloc(size_tsize),由于动态分配的空间计算机并不知道是用来做什么的所以是无类型的,但你要把它用在动态的整形数组上的时候就要显式的转换成int*了。 例2: malloc.c#include "iostream"using namespace std;main(){char *p;p=(char*)malloc(100*sizeof(char));if(p)printf("Memory Allocated at:%x \n",p);elseprintf("Not Enough Memory Available! \n");free(p);getchar();按任意键结束return 0;}