在我们通常理解的Stack 里,存在有不同的含义。简单的解释一下。

最常见的栈数据结构

最常见的含义就是栈,一种数组形式的储存形式,后进先出的特点,针对这样的数据结构,配套的函数应当:

代码存放的区域

stack 的另一种含义是存放数据的一种内存区域,参考维基百科 ,我们知道,程序包含几个区域,静态区,堆区,栈区。

下面这是个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
main.cpp
int a = 0; 全局初始化区
char *p1; 全局未初始化区
main()
{
int b; 栈
char s[] = "abc"; 栈
char *p2; 栈
char *p3 = "123456"; 123456在常量区,p3在栈上。
static int c =0; 全局(静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
分配得来得1020字节的区域就在堆区。
strcpy(p1, "123456"); 123456放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
}

对于stack 来说,stack 是有结构的,每个区块按照一定次序存放,可以明确知道每个区块的大小;但是heap 是没有结构的,数据可以任意的存放,因此,stack 的寻址速度要快于heap。

而且,一般来说,对每个线程会分配一个stack ,每个进程分配一个heap 。那么stack 就是线程独占的,而heap 则是线程共用的。stack 在创建的时候,大小是确定的,数据超过这个大小,就发生stack overflow 错误,而heap 的大小是不确定的,需要的话,可以不断的增加。

所以,只要是局部的,占用空间确定的数据,都会存放在stack 里边,其他的不确定的,动态生成的,就存放在heap 里去。

比如我们的创建新的对象,就会存放在heap中,因为stack 在使用完后会又编译器自动释放,但是heap 如果不去有效的清理,等待系统的垃圾清理机制去将这块内存清理,就很容易发生内存溢出。

更多详细的解释,可以参考这篇文章

代码运行的方式- 调用栈

第三种含义可以是调用栈,call stack 。它用的就是栈的思路,表示函数或者子例程像堆积木一样存放,以实现层层调用。

对于调用栈的方式,我们举个例子,该例子来自java 8 stack and heap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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方法。如图(来自阮一峰):

script>