堆和栈它们的内涵有多深
前言
堆(heap)
堆是一个内存空间,这个内存可以由程序员分配和释放,当然部分语言自带 GC( Garbage Collection 垃圾回收),部分堆内存可以由 GC 回收。这里千万要注意,这里说的「堆」和 数据结构 里面说的「堆」不是同一个概念,大家千万不要混淆。
栈(stack)
栈是由编译器自动分配和释放的,存放函数的参数值,局部变量的值等。也请注意,这里说的「栈」不是 数据结构 中的「栈」,大家千万不要混淆。这里请注意,栈是由由系统自动分配。
实际应用
堆、栈,算是相对底层一些的内容,大部分的语言其实这部分内容都是类似的。如果你不会 C# 语言也能看懂~。
我们都知道,C# 的数据类型有两大类型 —— 值类型 和 引用类型。大致结构如下图:
值类型我们看到包含内置值类型、用户定义的值类型和枚举。枚举就不用说了,内置值类型指的是 int、float、bool、double 等等。
通俗一点,堆上存放的是我们声明出来的实例对象,当我们需要访问这个实例对象时,我们找到它的方法是先找到变量对应在栈上的内存,然后通过栈上存放的数据,我们才能找到其真正的实例在堆的任意位置。
代码
class A{
public A(int x){
X = x;
}
public int X { get; set; }
}
static void Main(string[] args){
int m = 1;
int n = m;
m = 2;
Console.WriteLine($"m = {m}, n = {n}");
A a = new A(1);
var b = a;
a.X = 2;
Console.WriteLine($"a.X = {a.X}, b.X = {b.X}");
}
我们会发现输出结果是
m = 2, n = 1
a.X = 2, b.X = 2
我们发现 m 和 n 的值是分别独立的,而 a 和 b 修改其中一个会修改两个值。这是因为 m 和 n 都是分配在栈上的,而 a 和 b 虽然也是在栈上,但是其只是存储的堆上的一个地址索引,我们不管通过 a 还是 b 索引到的堆上的内存都是同一份。
我们再来看值类型和引用类型,在栈上的数据访问快,在堆上的数据访问相对慢,因此,当我们开发过程中,通过需求,比如底层的一些不变数据,完全可以有 struct 来实现,因为其不会为 null,符合值类型的要求,而且我们经常访问会更快一些。
Object a = 1;
int b = (int)a;
这两个都是合法语句。但是这里面隐藏了一个非常常见的一个现象,那就是装箱和拆箱。
什么是拆装箱?
当我们使用递归算法时,每次虽然调用的是同一个函数,但是会在栈中占用一个空间,只有走到最后的结束点后函数才能依次退出,而未到达最后的结束点之前,占用的栈空间一直没有释放。因此如果递归调用次数过多,就可能导致占用的栈资源超过线程的最大值,从而导致栈溢出,这也是为什么一定要尽量少用递归的原因。
上面说了很多,侧面说明了堆、栈的应用的优缺点,平时应用中需要更加了解我们写的代码都“干了什么”,这样才有可能写出更高效、更可靠的代码。对于一名程序员来说,不管未来编程语言发展的多么容易上手,一定不要忘了学习计算机的基础知识,哪怕是先学会了编程再返回来补习这些知识。祝大家工作顺利、评论留言少 BUG !点赞转发不脱发!
BY /
本文作者:力扣
编辑&版式:Janson
声明:本文归“力扣”版权所有,如需转载请联系。
点个在看,少个 bug
微信扫码关注该文公众号作者