[No0000136]6个重要的.NET概念:栈,堆,值类型,引用类型,装箱,拆箱
引言
本篇文章主要介绍.NET中6个重要的概念:栈,堆,值类型,引用类型,装箱,拆箱。文章开始介绍当你声明一个变量时,编译器内部发生了什么,然后介绍两个重要的概念:栈和堆;最后介绍值类型和引用类型,并说明一些有关它们的重要原理。
最后通过一个简单的示例代码说明装箱拆箱带来的性能损耗。
声明变量的内部机制
在.NET程序中,当你声明一个变量,将在内存中分配一块内存。这块内存分为三部分:1,变量名;2,变量类型;3,变量值。
下图揭示了声明一个变量时的内部机制,其中分配的内存类型依据你的变量类型。.NET中有两种类型的内存:栈内存和堆内存。在接下来的内容中,我们会了解到这两种类型的详细内容。

栈和堆
为了明白什么是栈和堆,先让我们看下下面示例代码的内部机制:
|
1
2
3
4
5
6
7
8
|
public void Method1(){// Line 1int i=4;// Line 2int y=2;//Line 3class1 cls1 = new class1();} |
这里一共有3行代码。让我们一下逐行看一下它们是如何执行的:
第1行:当这行代码执行时,编译器为它分配一小块栈内存。运行时栈负责提供程序所需的内存;
第2行:程序继续执行。如同名字一样,栈在第一块内存的顶部分配了一块内存。你也可以认为是模块或零件一块一块叠起来;
内存的分配与释放遵循后进先出(后进先出)逻辑,换句话说,内存只能在示例中i内存块的顶部分配或释放。
第3行:在第3行,我们创建了一个对象。当该行执行时,编译器在站上创建了一个指针,真实的对象存储在另一种叫“堆”的内存中。"堆"并不跟踪运行内存,它更像一堆随时可以访问的对象。堆用于动态分配内存。这里需要着重说明的是引用指针是分配在栈上。声明Class1 cls1时并不会给Class1的实例分配内存,而是分配一个栈变量cls1(并设置为null),然后把它指向“堆”。
退出方法:当方法退出时,它释放了栈上所有内存变量。换句话说,栈上所有的"Int"变量都依据后进先出的逻辑被释放掉了。要注意,此时不会释放堆内存,这种内存稍后会被“垃圾收集器”释放。
现在可能会有很多朋友奇怪为什么要分配2种内存,而不是仅用一种内存。
如果仔细观察,你会发现基本类型并不复杂,他们值包含简单的值,如i=0。对象数据类型很复杂,它们会引用其它对象或基本类型。换句话说,它要保持其它多种多样的引用,而每种类型必须存在内存中。对象类型需要动态内存而基本类型需要静态内存。如果需要分配动态内存,那么就分配到堆上;反之在栈上。

值类型与引用类型
现在我们明白了栈和堆,接下来看值类型和引用类型。值类型的数据和内存在同一个位置,而引用类型是一个指向内存的指针。
下面示例是一个整形数据类型变量i被赋给另一个整形数据类型变量j。它们的内存值都分配在栈上。当我们把一个int值分配给另外一个int值时,需要创建一个完全不同的拷贝。换句话说,你可以改变其中任何一个而不会影响另外一个。这种数据类型被称为值类型。
当我们创建一个对象,并把一个对象赋给另外一个对象时,它们的指针指向相同的内存(如下图,当我们把obj赋给obj1时,它们指向相同的内存)。换句话说,我们改变其中一个,会影响到另外一个,这种类型称为引用类型。

那么那种类型是值类型和引用类型呢?
在.NET中,依据数据类型,变量被分配到堆或栈上。“string”和"Object"是引用类型,其他基本类型被分配到栈上,是值类型,如下图:
装箱与拆箱
通过上面学习,我们学到了很多有用的东西,其中最有用的是明白了当把数据从栈移动到堆上时会有性能损失。如下图实例,当我们把一个值类型装箱为引用类型时,数据从栈移动到堆上。反之,数据从堆移动到栈上。这种在堆和栈之间的移动带来了性能的损失。数据从值类型转变为引用类型的过程称为“装箱”,反之为“拆箱”。
如果编译上面的代码,在ILDASM中看IL代码就会发下如何进行装箱拆箱操作的,如下:

装箱拆箱的性能影响
为了揭示装箱拆箱如何影响性能,我们把下面代码运行10000次。一个函数有装箱操作,另一个只有简单代码。我们用简单的计时器看它们的运行时间。装箱函数耗时 3542 MS,无装箱操作的耗时2477MS。这说明在实际项目中,除非必须,否则应避免装箱,拆箱操作。

[No0000136]6个重要的.NET概念:栈,堆,值类型,引用类型,装箱,拆箱的更多相关文章
- 6个重要的.NET概念:栈,堆,值类型,引用类型,装箱,拆箱
引言 本篇文章主要介绍.NET中6个重要的概念:栈,堆,值类型,引用类型,装箱,拆箱.文章开始介绍当你声明一个变量时,编译器内部发生了什么,然后介绍两个重要的概念:栈和堆:最后介绍值类型和引用类型,并 ...
- .NET的堆和栈02,值类型和引用类型参数传递以及内存分配
在" .NET的堆和栈01,基本概念.值类型内存分配"中,了解了"堆"和"栈"的基本概念,以及值类型的内存分配.我们知道:当执行一个方法的时 ...
- C#【堆与栈 值类型 引用类型】
先说C#中值类型和引用类型 概念: 1.值类型:数据存储在内存的堆栈中,从堆栈中可以快速地访问这些数据,因此,值类型表示实际的数据. 2.引用类型:表示指向存储在内存堆中的数据的指针或引用(包括类.接 ...
- 深入C#内存管理来分析值类型&引用类型,装箱&拆箱,堆栈几个概念组合之间的区别
C#初学者经常被问的几道辨析题,值类型与引用类型,装箱与拆箱,堆栈,这几个概念组合之间区别,看完此篇应该可以解惑. 俗话说,用思想编程的是文艺程序猿,用经验编程的是普通程序猿,用复制粘贴编程的是2B程 ...
- 栈和托管堆/值类型和引用类型/强制类型转换/装箱和拆箱[C#]
原文地址:http://www.cnblogs.com/xy8.cn/articles/1227228.html 一.栈和托管堆 通用类型系统(CTS)区分两种基本类型:值类型和引用类型.它 ...
- js的基础(平民理解的执行上下文/调用堆栈/内存栈/值类型/引用类型)
与以前的切图比较,现在的前端开发对js的要求似乎越来越高,在开发中,我们不仅仅是要知道如何运用现有的框架(react/vue/ng), 而且我们对一些基础的知识的依赖越来越大. 现在我们就用平民的方法 ...
- 【译】.NET中六个重要的概念:栈、堆、值类型、引用类型、装箱和拆箱
为何要翻译 一来是为了感受国外优秀技术社区知名博主的高质量文章,二来是为了复习对.NET技术的基础拾遗达到温故知新的效果,最后也是为了锻炼一下自己的英文读写能力.因为是首次翻译英文文章(哎,原谅我这个 ...
- .NET中六个重要的概念:栈、堆、值类型、引用类型、装箱和拆箱 (转)
作者: Edison Chou 来源: 博客园 发布时间: 2014-09-03 15:59 阅读: 318 次 推荐: 2 原文链接 [收藏] 原文作者:Shivprasad k ...
- .NET中的六个重要概念:栈、堆、值类型、引用类型、装箱和拆箱
为何要翻译 一来是为了感受国外优秀技术社区知名博主的高质量文章,二来是为了复习对.NET技术的基础拾遗达到温故知新的效果,最后也是为了锻炼一下自己的英文读写能力.因为是首次翻译英文文章(哎,原谅我这个 ...
随机推荐
- iOS APP 安全测试
1.ipa包加壳 首先,我们可以通过iTunes 下载 AppStore的ipa文件(苹果 把开发者上传的ipa包 进行了加壳再放到AppStore中),所以我们从AppStore下载的ipa都是加壳 ...
- mvc4 强大的导出和不需要上传文件的批量导入EXCEL--SNF快速开发平台3.1
数据的导入导出,在很多系统里面都比较常见,这个导入导出的操作,在Winform里面比较容易实现,但在Web上我们应该如何实现呢?本文主要介绍利用MVC4+EasyUI的特点,并结合文件上传控件,实现文 ...
- Cacti 1.1.6 添加monitor和thold插件
以前一直使用0.8版本的cacti,最近升级到1.1.6之后,发现以前0.8用的插件已经不适用了,需要下载新的插件包进行导入到下面网址获取Cacti插件包https://github.com/Cact ...
- 掌握Docker命令-Docker for Web Developers(4)
1.管理镜像命令 获取镜像 docker push ubuntu:14:04 查看镜像列表 docker images 重命名image docker tag IMAGE-NAME NEW-IMAGE ...
- openfire接收离线消息
先接收离线消息后再通知openfire上线 //获取离线消息 OfflineMessageManager offlineMessageManager=new OfflineMessageManager ...
- 【论文笔记】使用SPSS 进行 T Test (T检验)
从具有t值来看,你是在进行T检验.T检验是平均值的比较方法. T检验分为三种方法: 1. 单一样本t检验(One-sample t test),是用来比较一组数据的平均值和一个数值有无差异.例如,你选 ...
- Pitch detection algorithm(基音搜索算法)PDA相关链接
第一:维基百科 http://en.wikipedia.org/wiki/Pitch_estimation 简要系统介绍了基音估计算法的分类和一些链接,论文 第二:http://ws2.bingham ...
- MXNET:监督学习
线性回归 给定一个数据点集合 X 和对应的目标值 y,线性模型的目标就是找到一条使用向量 w 和位移 b 描述的线,来尽可能地近似每个样本X[i] 和 y[i]. 数学公式表示为\(\hat{y}=X ...
- java.util.concurrent介绍【转】
java.util.concurrent介绍 java.util.concurrent 包含许多线程安全.测试良好.高性能的并发构建块.不客气地说,创建 java.util.concurrent ...
- Virtualbox的centos7 nat和桥接网络配置
在实际配置虚拟机的过程中,网络配置时候一个很繁琐的过程,经常一个点没注意到,就访问不了了.在此,做一个简单的教程以供后续使用时可以参考! 方法一: 使用NAT网络 1. 选择网卡 安装centos7的 ...