栈与堆的区别
关于内存的使用,栈(stack)和堆(heap)是非常重要的两个概念,网上讲解的资料也比较多,大家也应该知道栈和堆分别的用途是什么,接下来说一下我对栈与堆的本质区别的理解。
每个程序在运行时系统都会分配一块叫做栈的连续的内存区域,大小一般为1M或2M,是编译程序时指定的常数。堆则是系统中所有空闲的内存区域,因此是不连续的,而且有可能是虚拟内存。函数的调用和返回是通过栈来实现的,不细说了。程序中用到的变量(对象)所占据的内存空间既可以从栈上分配,也可以从堆中分配,区别如下:
1. 内存指针的性质不同
栈上面只能分配长度较小、大小固定的数据,变量的内存地址相对于栈指针的偏移量在编译时就可以确定,因而可以生成直接的内存访问的指令。
堆上面分配的空间大小在运行时指定,并且返回的内存地址只能在运行时得知,因此栈上需要有一个相应的变量来保存堆上分配的内存地址,地址的长度为32位或64位。于是访问堆上的内存单元只能通过间接访问的指令来操作。
2. 内存空间的回收方式不同
栈上面分配的内存在压栈和出栈的过程中自动分配自动回收,速度很快。
堆上面分配的内存则需要显式地释放掉或者做垃圾回收的处理,有可能会漏掉释放,造成所谓的内存泄漏。
理解栈和堆的概念对于编写正确的高效的程序非常重要,但是程序语言的语法对栈和堆的体现很隐晦。C++创建一个类的实例时,既可以指定在栈上分配,也可以指定在堆上分配。C#中值类型的变量在栈上分配,引用类型的变量在堆上分配,值类型的变量也可以通过装箱的方式在堆上分配,在unsafe代码中可以在栈上分配大小固定的字节数组,总的来说没有C++灵活。
最后做一个练习,思考一下下面的程序在运行中内存是怎样分配的:
public struct A
{
int field;
List<int> list = new List<int>();
}
public class B
{
int field;
List<A> list = new List<A>();
}
public class P
{
static void main(string[] args)
{
A a = new A();
B b = new B();
Console.Write("{0} and {1}", a, b);
}
}
{
int field;
List<int> list = new List<int>();
}
public class B
{
int field;
List<A> list = new List<A>();
}
public class P
{
static void main(string[] args)
{
A a = new A();
B b = new B();
Console.Write("{0} and {1}", a, b);
}
}
分类:
Programming
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述