Stack的三种含义_最新动态_新闻资讯_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 新闻资讯 > 最新动态 > Stack的三种含义

Stack的三种含义

 2013/11/29 12:27:11    程序员俱乐部  我要评论(0)
  • 摘要:学习编程的时候,经常会看到stack这个词,它的中文名字叫做"栈"。理解这个概念,对于理解程序的运行至关重要。容易混淆的是,这个词其实有三种含义,适用于不同的场合,必须加以区分。含义一:数据结构stack的第一种含义是一组数据的存放方式,特点为LIFO,即后进先出(Lastin,firstout)。在这种数据结构中,数据像积木那样一层层堆起来,后面加入的数据就放在最上层。使用的时候,最上层的数据第一个被用掉,这就叫做"后进先出"。与这种结构配套的,是一些特定的方法,主要为下面这些。push
  • 标签:
class="topic_img" alt=""/>

  学习编程的时候,经常会看到 stack 这个词,它的中文名字叫做"栈"。

  理解这个概念,对于理解程序的运行至关重要。容易混淆的是,这个词其实有三种含义,适用于不同的场合,必须加以区分。

  含义一:数据结构

  stack 的第一种含义是一组数据的存放方式,特点为 LIFO,即后进先出(Last in, first out)。

数据结构 stack

  在这种数据结构中,数据像积木那样一层层堆起来,后面加入的数据就放在最上层。使用的时候,最上层的数据第一个被用掉,这就叫做"后进先出"。

  与这种结构配套的,是一些特定的方法,主要为下面这些。

  • push:在最顶层加入数据。
  • pop:返回并移除最顶层的数据。
  • top:返回最顶层数据的值,但不移除它。
  • isempty:返回一个布尔值,表示当前 stack 是否为空栈。

  含义二:代码运行方式

  stack 的第二种含义是"调用栈"(call stack),表示函数或子例程像堆积木一样存放,以实现层层调用。

  下面以一段 Java 代码为例(来源)。

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 (String[] args) {
Student s;
s = new Student (23,"Jonh"); }
}

  上面这段代码运行的时候,首先调用 main 方法,里面需要生成一个 Student 的实例,于是又调用 Student 构造函数。在构造函数中,又调用到 setName 方法。

调用栈

  这三次调用像积木一样堆起来,就叫做"调用栈"。程序运行的时候,总是先完成最上层的调用,然后将它的值返回到下一层调用,直至完成整个调用栈,返回最后的结果。

  含义三:内存区域

  stack 的第三种含义是存放数据的一种内存区域。程序运行的时候,需要内存空间存放数据。一般来说,系统会划分出两种不同的内存空间:一种叫做 stack(栈),另一种叫做 heap(堆)。

内存区域 stack

  它们的主要区别是:stack 是有结构的,每个区块按照一定次序存放,可以明确知道每个区块的大小;heap 是没有结构的,数据可以任意存放。因此,stack 的读取速度要比 heap 快。

内存区域 heap

  其他的区别还有,一般来说,每个线程分配一个 stack,每个进程分配一个 heap,也就是说,stack 是线程独占的,heap 是线程共用的。此外,stack 创建的时候,大小是确定的,数据超过这个大小,就发生 stack overflow 错误,而 heap 的大小是不确定的,需要的话可以不断增加。

  根据上面这些区别,数据存放的规则是:只要是局部的、占用空间确定的数据,一般都存放在 stack 里面,否则就放在 heap 里面。请看下面这段代码(来源)。

public void Method1(){
int i=4;
  int y=2;
  class1 cls1 = new class1();
}

  上面代码的 Method1 方法,共包含了三个变量:i, y 和 cls1。其中,i和y的值是整数,内存占用空间是确定的,而且是局部变量,只用在 Method1 区块之内,不会用于区块之外。cls1 是指针变量,指向一个对象的实例,指针变量占用的大小是确定的,但是对象实例以目前的信息无法确知所占用的内存空间大小。

  这三个变量和一个对象实例在内存中的存放方式如下。

内存空间 stack 实例

  从上图可以看到,i、y和 cls1 都存放在 stack,因为它们占用内存空间都是确定的,而且本身也属于局部变量。但是,cls1 指向的对象实例存放在 heap,因为它的大小不确定。作为一条规则可以记住,所有的对象都存放在 heap。

  接下来的问题是,当 Method1 方法运行结束,会发生什么事?

  回答是整个 stack 被清空,i、y和 cls1 这三个变量消失,因为它们是局部变量,区块一旦运行结束,就没必要再存在了。而 heap 之中的那个对象实例继续存在,直到系统的垃圾清理机制(garbage collector)将这块内存回收。因此,一般来说,内存泄漏都发生在 heap,即某些内存空间不再被使用了,却因为种种原因,没有被系统回收。

  • 相关文章
发表评论
用户名: 匿名