news 2026/6/16 4:32:33

用最简单的解释告诉你C#中堆栈和内存的关系

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用最简单的解释告诉你C#中堆栈和内存的关系

在学习C#的过程中,很多初学者会被“堆栈”“内存”这些概念绕晕,甚至误以为“堆栈”是独立于内存之外的东西。其实答案很简单:内存是程序运行时的“整块储物空间”,而堆栈(栈+堆)只是这块大空间里划分出的两个功能不同的“小区域”。就像家里的大衣柜,栈是随手放钥匙、手机的抽屉,堆是挂大衣、放被子的挂区,两者分工明确,配合起来才能让“衣物收纳”(程序运行)顺畅高效。

先搞懂:内存里的“快速抽屉”——栈(Stack)

栈是内存中专门负责“快速存取临时数据”的区域,就像衣柜里的小抽屉,只能放小件、常用的物品,而且取放规则很固定:“先进后出”(先放进去的东西要最后才能拿出来)。

在C#程序里,栈主要存放这些东西:方法里的局部变量、函数的参数、程序运行的临时状态等。比如以下代码中,int age局部变量、string name局部变量,还有CalculateSum方法的ab参数,都会存在栈里:

// 示例代码片段 static void Main() { int age = 25; // 局部变量,存栈中 string name = "张三"; // 引用存栈中,字符串对象存堆中 int sum = CalculateSum(10, 20); // 10、20参数存栈中 } static int CalculateSum(int a, int b) // a、b参数存栈中 { return a + b; }

栈的特点特别好记:一是存取速度极快,程序会自动帮你“放”和“收”——方法执行开始时,局部变量自动进栈;方法执行结束后,栈里的这些变量会被自动清理,根本不用你手动管理;二是空间有限,就像小抽屉装不下大件物品,要是局部变量太多、嵌套调用方法层数太深,还可能出现“栈溢出”的错误。

再明白:内存里的“大容量挂区”——堆(Heap)

堆是内存中负责“存放长期、大容量数据”的区域,对应衣柜的挂区,能放体积大、需要长期使用的物品,而且没有“先进后出”的限制,想放哪里、取哪里都可以。

C#里那些“用new关键字创建的对象”,都存在堆里。比如以下代码中new Person()创建的Person对象本身、Person类的Name属性对应的后台字段,都躺在堆里。除此之外,字符串、数组等需要动态分配空间的数据,也会存在堆里:

// 示例代码片段 class Person { public string Name { get; set; } // 属性后台字段存堆中 } static void Main() { Person person = new Person(); // new创建的对象存堆中 person.Name = "李四"; // 字符串对象"李四"存堆中 int[] scores = new int[3] { 90, 85, 95 }; // 数组对象存堆中 }

堆的特点和栈正好互补:一是空间大,能存放栈放不下的“大件数据”;二是不会自动清理——堆里的对象创建后,会一直存在,直到C#的“垃圾回收器”(GC)发现它没人用了,才会过来清理;三是存取速度比栈慢,因为堆里的数据没有固定顺序,程序需要先找到数据的“地址”才能访问。

关键配合:栈里存“地址”,堆里存“实物”

很多人困惑的点在于:栈和堆不是孤立的,而是靠“地址引用”配合工作的。我们用一段完整的核心代码举例,一看就懂:

class Student { public int Score { get; set; } // 属性后台字段存堆中 } static void Main() { Student stu = new Student(); // 关键代码:栈与堆配合 stu.Score = 98; // 赋值操作的栈堆协同 }

这行代码执行时,会发生两件事:

1. 等号左边的stu变量(这是一个“引用”),会被存到里——它就像一张“地址纸条”,只记录着堆里Student对象的位置,本身很小;

2. 等号右边的new Student()创建的Student对象(包括它的Score属性、对应的后台字段),会被存到里——这是真正的“实物”,占用的空间比栈里的“地址纸条”大得多。

后续写stu.Score = 98;赋值时,程序会先从栈里找到stu这张“地址纸条”,跟着地址找到堆里的Student对象,再修改它的Score字段;如果后续写int studentScore = stu.Score;,程序也是先通过栈里的地址找到堆里的对象,再把Score的值取出来,存到栈里的studentScore变量中。

总结:记住3句话,再也不混淆

1. 内存是“大整体”,堆栈是内存里的“两个功能区”,不是独立存在的;

2. 栈放“小而临时”的东西(局部变量、参数、引用地址),自动清理、速度快;

3. 堆放“大而长期”的东西(new出来的对象、数组),需要GC清理、靠栈里的地址访问。

理解了这个关系,再看C#属性访问器对应的IL代码(比如自动属性的get、set访问器)就会更清晰:IL指令里的ldarg.0(取当前对象的引用,存于栈中)、ldfld(根据地址去堆里取字段),本质上就是在协调栈和堆的配合工作。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/14 3:54:53

终极s3fs-fuse使用指南:简单配置云端存储同步方案

终极s3fs-fuse使用指南:简单配置云端存储同步方案 【免费下载链接】s3fs-fuse FUSE-based file system backed by Amazon S3 项目地址: https://gitcode.com/gh_mirrors/s3/s3fs-fuse 你是否正在为本地服务器与云端存储之间的数据同步而烦恼?s3fs…

作者头像 李华
网站建设 2026/6/16 4:32:25

Jellyfin Bangumi插件配置指南:轻松管理中文动画元数据

还在为Jellyfin中的动画元数据不完整而烦恼吗?Jellyfin Bangumi插件是专为中文用户设计的解决方案,能够自动从Bangumi获取高质量的中文动画元数据,并实现播放进度与Bangumi账号的完美同步。 【免费下载链接】jellyfin-plugin-bangumi bgm.tv …

作者头像 李华
网站建设 2026/6/15 3:34:59

使用EmotiVoice进行声音克隆的技术细节与隐私边界探讨

使用EmotiVoice进行声音克隆的技术细节与隐私边界探讨 在AI语音技术飞速发展的今天,我们正逐步告别机械朗读的时代。当你听到一段语音时,可能已经无法分辨它是出自真人之口,还是由算法生成——而这正是像 EmotiVoice 这样的现代TTS系统带来的…

作者头像 李华
网站建设 2026/6/15 20:38:58

IndexTTS2终极配置指南:快速提升语音合成质量的完整方案

IndexTTS2终极配置指南:快速提升语音合成质量的完整方案 【免费下载链接】index-tts An Industrial-Level Controllable and Efficient Zero-Shot Text-To-Speech System 项目地址: https://gitcode.com/gh_mirrors/in/index-tts 还在为语音合成效果不佳而烦…

作者头像 李华
网站建设 2026/6/14 23:03:40

参考文献在哪里找:实用查找方法与途径指南

传统的文献搜索,是我们去适应机器的逻辑:拆解关键词、使用布尔运算符(AND, OR, NOT)。而新一代的AI学术工具,正在让机器来适应人类的思维:它们能理解模糊的问题,能联想相关的概念,甚…

作者头像 李华