news 2026/5/26 3:15:01

用最简单的解释告诉你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/5/26 5:22:07

Moonlight for Tizen:让三星智能电视变身免费游戏主机

Moonlight for Tizen:让三星智能电视变身免费游戏主机 【免费下载链接】moonlight-chrome-tizen A WASM port of Moonlight for Samsung Smart TVs running Tizen OS (5.5 and up) 项目地址: https://gitcode.com/gh_mirrors/mo/moonlight-chrome-tizen 还在…

作者头像 李华
网站建设 2026/5/26 0:55:08

EmotiVoice语音合成边缘触发机制:低延迟响应策略

EmotiVoice语音合成边缘触发机制:低延迟响应策略 在智能家居设备日益复杂的今天,用户对语音助手的期待早已超越“能听会说”的基础功能。他们希望听到的是带有情绪温度的声音——一句温柔的早安问候、一段愤怒的游戏NPC台词,甚至是一个熟悉亲…

作者头像 李华
网站建设 2026/5/24 7:25:57

高表现力语音合成开源工具EmotiVoice上手体验报告

高表现力语音合成开源工具EmotiVoice上手体验报告 在虚拟主播直播带货、AI陪伴机器人深夜谈心、游戏NPC因剧情转折怒吼或啜泣的今天,我们对“声音”的期待早已超越了“把字读出来”。人们想要的是能笑、会生气、懂得安慰人的声音——有情绪的声音。这正是传统文本转…

作者头像 李华
网站建设 2026/5/24 19:08:23

Adobe Illustrator脚本工具终极指南:快速提升设计效率

Adobe Illustrator脚本工具终极指南:快速提升设计效率 【免费下载链接】illustrator-scripts Adobe Illustrator scripts 项目地址: https://gitcode.com/gh_mirrors/il/illustrator-scripts 在Adobe Illustrator的日常使用中,您是否经常遇到这些…

作者头像 李华
网站建设 2026/5/26 2:03:08

避开绩效考核误区:实时反馈系统的正确打开方式

在企业人力资源管理中,绩效考核的核心目标是推动员工成长与组织效率提升,而实时反馈正是实现这一目标的关键环节。传统绩效考核模式中,反馈滞后、信息脱节等问题往往导致考核流于形式,难以真正发挥指导作用。绩效考核系统实时反馈…

作者头像 李华
网站建设 2026/5/23 20:30:00

实战指南:5步掌握Ant Design X of Vue构建智能对话界面

实战指南:5步掌握Ant Design X of Vue构建智能对话界面 【免费下载链接】ant-design-x-vue Ant Design X For Vue.(WIP) 疯狂研发中🔥 项目地址: https://gitcode.com/gh_mirrors/an/ant-design-x-vue 还在为AI对话界面的开…

作者头像 李华