内存中堆栈与数据结构中的堆栈,以前一直被这困扰着,不知道的时候还以为是同一个东西呢。等看一些资料后,发现原来二者并不是同一概念。现将一些特点记录如下,如有不正之处,还望看到的童鞋指正,谢谢。
首先,二者肯定是不同的概念。数据结构中栈是指满足先进后出的性质的数学或数据结构,数据结构中的堆一般而言,是指(满足堆性质的)优先队列的数据结构,第一个元素具有最高的优先权。
下面来介绍下内存中的堆栈。在进行C/C++编程时,需要我们对内存的了解比较精准。对于一个进程的内存空间而言,可以在逻辑上分成3个部分:代码区、静态数据区和动态数据区。其中动态数据区一般就是“堆栈”。“栈stack”和“堆heap”是两种不同的动态数据区。下面为了方便,我们把内存中“栈”叫栈区,“堆”叫堆区。下面对其进行分别介绍:
栈区(stack):栈区的空间由操作系统自动分配和释放,该部分主要用于存放函数的参数值、局部变量等,比如声明在函数中的一个局部变量int b,系统就会自动在栈中为b开辟空间。栈区的操作方式类似于数据结构中栈(这也许是造成许多人混淆的地方,正如有的人所说,我们可以把数据结构的栈理解成某个技术,而内存的栈正好用到了该技术,但二者其实并不一样)。另外需要注意的是,在windows下,栈是向低地址扩展的数据机构,是一块连续的内存区域。也就是说栈顶的地址和栈的最大容量是系统预先设定好的,比如在windows下,栈的大小为2MB(也有的说是1MB,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间,将会提示overflow。总之就是说栈的空间是有限的。
堆区(heap):堆区空间一般由程序员分配和释放(需要注意堆区与数据结构中的堆是两回事,其分配方式类似于链表),比如,在C中用malloc函数--- p1 = (char*) malloc(10); 在C++中用new,都将分配堆区空间。不过要注意p1本身是在栈中。
静态数据区:全局变量和静态变量都存放于该区。初始化的全局变量和初始化的静态变量放在一块区域,未初始化的全局变量和未初始化的静态变量放在相邻的另一区域。程序结束后由系统自动释放。
代码区:该区用于存放函数体的二进制代码。
代码区(code area)
|
程序内存空间
|
全局数据区(data area)
| |
堆区(heap area)
| |
栈区(stack area)
|
int a = 0; //全局初始化区
char *p1; //全局未初始化区
int main() {
int b; //栈
char s[] = /"abc/"; //栈
char *p2; //栈
char *p3 = /"123456/"; //123456//0在常量区,p3在栈上。
static int c =0;//全局(静态)初始化区
p1 = new char[10];
p2 = new char[20];
//分配得来得和字节的区域就在堆区。
strcpy(p1, /"123456/"); //123456//0放在常量区,编译器可能会将它与p3所指向的/"123456/"优化成一个地方。
}
|
int main(){
char a = 1;
char c[] = /"1234567890/";
char *p =/"1234567890/";
a = c[1];
a = p[1];
return 0;
}
|
10: a = c[1];
00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh] 0040106A 88 4D FC mov byte ptr [ebp-4],cl 11: a = p[1]; 0040106D 8B 55 EC mov edx,dword ptr [ebp-14h] 00401070 8A 42 01 mov al,byte ptr [edx+1] 00401073 88 45 FC mov byte ptr [ebp-4],al |
class Time{
public:
Time(int,int,int,string);
~Time(){
cout<</"call Time/'s destructor by:/"<<name<<endl;
}
private:
int hour;
int min;
int sec;
string name;
};
Time::Time(int h,int m,int s,string n){
hour=h;
min=m;
sec=s;
name=n;
cout<</"call Time/'s constructor by:/"<<name<<endl;
}
int main(){
Time *t1;
t1=(Time*)malloc(sizeof(Time));
free(t1);
Time *t2;
t2=new Time(0,0,0,/"t2/");
delete t2;
system(/"PAUSE/");
return EXIT_SUCCESS;
}
|