理解stack栈对于理解程序的运行至关重要。容易混淆的是,这个词其实有三种含义,适用于不同的场合,必须加以区分。
含义一:数据结构
stack的第一种含义是一组数据的存放方式,特点为LIFO,即后进先出(Last in,first out)。
在这种数据结构中,数据像积木那样一层层堆起来,后面加入的数据就放在最上层。使用的时候,最上层的数据第一个被用掉,这就叫做"后进先出"。
与这种结构配套的是下面几种特定的方法:
(1)push:在最顶层加入数据
(2)pop:返回并移除最顶层的数据
(3)top:返回最顶层数据的值,但不移除它
(4)isempty:返回一个布尔值,表示当前stack是否为空栈。
含义二:代码运行方式
stack的第二种含义是“调用栈”,表示函数或子例程像堆积木一样存放,以实现层层调用。
class Student
{
int age;
string name;
public student(int age,string name)
{
this.age=age;
setName(Name);
}
public void setName(string name)
{
this.name=Name;
}
}
public class Main()
{
public static void main()
{
student s;
s=new student(23,"John");
}
}
上面代码运行的时候,首先调用main方法,里面需要生成一个student的实例,于是又调用student构造函数。在构造函数中又调用setName方法。
含义三:内存区域
stack栈的第三种含义是存放数据的一种内存区域。程序运行的时候,需要内存空间存放数据。一般来说系统会划分出两种不同的内存空间:一种叫stack(栈),另一种叫做heap(堆).
它们的主要区别是:stack是有结构的,每个区块按照一定的次序存放,可以明确知道每个区块的大小;heap是没有结构的,数据可以任意存放。因此,stack的寻址速度要快于heap。
其他的区别还有,一般来说,每个线程分配一个stack,每个进程分配一个heap,也就是说,stack是线程独占的,heap是线程共用的。此外,stack创建的时候,大小是确定的,数据超过这个大小,就发生stack overflow错误,而heap的大小是不确定的,需要的话可以不断增加。
根据上面这些区别,数据存放的规则是:只要是局部的、占用空间确定的数据,一般都存放在stack里面,否则就放在heap里面。
public void Method()
{
int i=4;
int y=2;
class cls1=new class1();
}
上面代码的Method方法,共包含三个变量:i、y、cls1.其中,i和y的值是整数,内存占有空间是确定的,而且是局部变量,只有在Method区块之间,不会用于区块之外。cls1也是局部变量,但是类型为指针变量,指向一个对象的实例.指针变量占用的大小是确定的,但是对象实例以目前的信息无法确知所占用的内存空间大小.
因此,i、y、cls1都存放在stack,因为它们占用内存空间都是确定的,而且本身也属于局部变量。但是,cls1指向的对象实例存放在heap,因为它的大小不确定。
作为一条潜规则需要记住,所有的对象都存放在heap。
接下来的问题是,当Method方法运行结束,会发生什么事?
回答是整个stack被清空,i、y和cls1这三个变量消失,因为它们是局部变量,区块一旦运行结束,就没必要再存在了。而heap之中的那个对象实例继续存在,直到系统的垃圾清理机制(garbage collector)将这块内存回收。因此,一般来说,内存泄漏都发生在heap,即某些内存空间不再被使用了,却因为种种原因,没有被系统回收。
Stack栈的三种含义
最新推荐文章于 2023-10-12 20:19:51 发布