关于堆栈的详解

         在计算机领域,堆栈是一个不容忽视的概念,是两种数据结构

         堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除。

         要点:

         堆,列队优先,先进先出。

         栈,先进后出(First-In/Last-Out)。

         栈(操作系统): 在函数调用时,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。全局变量和静态变量的存储是放在一块的,都放在全局区(静态区),初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放空间。

         当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向函数的返回地址,也就是主函数中的下一条指令的地址,程序由该点继续运行。

        堆(操作系统): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。堆则是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些

         堆(数据结构):堆可以被看成是一棵树,如:堆排序

         栈(数据结构):一种先进后出的数据结构

         栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据可以共享,详见第3点。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器.但缺点是,由于要在运行时动态分配内存,存取速度较慢。

         堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容由程序员安排。

另外,栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义: 

         int a=3;

         int b=3;

         编译器先处理int a= 3;首先它会在栈中创建一个变量为a的引用,然后查找有没有字面值为3的地址,没找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处理intb= 3;在创建完b的引用变量后,由于在栈中已经有3这个字面值,便将b直接指向3的地址。这样,就出现了a与b同时均指向3的情况。

         特别注意的是,这种字面值的引用与类对象的引用不同。假定两个类对象的引用同时指向一个对象,如果一个对象引用变量修改了这个对象的内部状态,那么另一个对象引用变量也即刻反映出这个变化。相反,通过字面值的引用来修改其值,不会导致另一个指向此字面值的引用的值也跟着改变的情况。如上例,我们定义完a与b的值后,再令a=4;那么,b不会等于4,还是等于3。在编译器内部,遇到a=4;时,它就会重新搜索栈中是否有4的字面值,如果没有,重新开辟地址存放4的值;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。

这里有必要对变量的存储方式进行说明:

在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区

  1.栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。

  2.堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete.如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。

  3.自由存储区,就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。

  4.全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。

  5.常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改)

 变量存储特性:

存储描述

持续性

作用域

链接性

如何声明

自动

自动

代码块

在代码块中

寄存器

自动

代码块

在代码块中,使用关键字 register

静态,无链接性

静态

代码块

在代码快中,使用关键字 static

静态,外部链接性

静态

文件

外部

不在任何函数内

静态,内部链接性

静态

文件

内部

不在任何函数内,使用关键字 static

         首先,定义静态变量时如果没有初始化编译器会自动初始化为0.。接下来,如果是使用常量表达式初始化了变量,则编译器仅根据文件内容(包括被包含的头文件)就可以计算表达式,编译器将执行常量表达式初始化。必要时,编译器将执行简单计算。如果没有足够的信息,变量将被动态初始化。

         所有的静态持续变量都有下述初始化特征:        未被初始化的静态变量的所有位都被设为0。这种变量被称为零初始化。以上代码说明关键字static的两种用法,但含义有些不同:用于局部声明,以指出变量是无链接性的静态变量时,static表示的是存储持续性;而用于代码块外声明时,static表示内部链接性,而变量已经是静态持续性了。有人称之为关键字重载,即关键字的含义取决于上下文。

请看一下代码:

#include<iostream>
using namespace std;
int global_1=1000;         //静态变量外部链接性,存放在静态区
int global_2;              //静态变量外部链接性,存放在静态区
static intone_file_1=1000; //静态变量内部链接性,存放在静态区
static intone_file_2;      //静态变量内部链接性,存放在静态区
int func(int a,int b);      
int main()
{
    static int count_1=1000;//静态变量无链接性,存放在静态区
    int t;                  //普通变量,存放在栈
    char s[] = "abc";       //普通变量,存放在栈 
    char *p2;               //普通变量,存放在栈
    char *p3 = "123456";    //123456\0在常量区,p3在栈上。
    cr=func(t,p);           //函数返回值,实参等都存放在栈
    p1 = (char *)malloc(10); //动态分配的内存空间,存放在堆 
    p2 = (char *)malloc(20); //动态分配的内存空间,存放在堆

    return 0;
}


 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值