您的位置:首页 > 其它

(英文翻译)六条.net中非常重要的知识点:堆,栈,值类型,引用类型,装箱和拆箱

2012-06-19 17:34 369 查看

介绍

  这篇文章我将会介绍六个非常重要的概念:堆,栈,值类型,引用类型,装箱和拆箱。我会从声明一个变量开始,解释堆和栈,然后再逐个介绍值类型,引用类型,以及它们的实现原理,最后我会给出一小段代码来解释装箱和拆箱。

当你声明一个变量时,系统到底干了些什么?

  答案:当你在程序中声明了一个变量后,系统会在内存上划分一段数据块,用来保存你声明的变量,里面包含三条非常重要的数据:1,变量名2,变量的类型3,变量的值

  上面的解释可能过于简单。实际上,系统会根据你声明的变量类型来决定分配到哪种内存上,主要有堆内存和栈内存。接下来我会继续讨论这两种不同的内存分配方式。



  为了解释堆和栈,我写了一小段代码

public void Method1()
{
// Line 1
int i=4;

// Line 2
int y=2;

//Line 3
class1 cls1 = new class1();
}


  让我们来逐行解释以上三行代码:

  当执行到第一行代码的时候,JIT将会在栈内存中开辟一个地址空间用来保存你的值。由栈内存来负责程序运行时的历史内存开销。

  当执行到第二行代码的时候,JIT会在上一次分配栈内存的地址之上再开一个新的内存空间用来存放现在的变量。这就好比是把一个箱子放到另外一个箱子的上面。栈也叫迭代式寄存器。当我们需要取这些盒子的时候,就必须遵循后进先出的规则。言下之意就是一定要从最顶部取箱子。

  在第三行,我们实例化了一个类。当这句代码执行后,JIT会在栈内存中开辟一个新的内存空间用来存放一个指针类型的数据,实际的内存开销是分配在另外一种类型的内存中:堆内存。堆存放数据的特点是以一种链表的形式存放。当系统收到请求时,会遍历空闲节点链表,寻找第一个大于所申请空间的堆节点。然后从空闲节点链表中删除该节点,最后将空间返回给JIT。

  大家一定要注意的是,指针是分配到栈当中的。但是你的代码如果是Class1 cls1;执行这段代码是不会在堆中分配内存的,实际上它会在栈中保存一个名为cls1的变量,并且值为NUll.只有当执行New的操作时,才会在堆中分配内存。

  当方法执行完毕之后,分配在栈中的变量会以后进先出的顺序被系统自动回收。而分配在堆中的变量会在稍后被GC回收。(以下是整个代码执行流程中内存分配的类型图)

  



  

  写到这里,可能有的程序员会问,为什么会有两种内存的分配方式。我们能不能只使用一种方式来分配内存呢?如果你仔细观察就会发现,最开始的时候我们的数据都是比较简单的,类似" int i=1;".但当有了Object类型后,我们的数据类型就复杂很多了,一个Object类型可能会引用到好多个Object类型以及简单的数据类型。Object类型需要动态的分配内存,而简单的数据类型需要静态的分配内存。如果需要动态的分配内存,我们是分配到堆内存还是栈内存?



值类型和引用类型

  现在我们基本上以及理解了堆栈的区别。接下来我们就来区别一下什么是值类型,什么是引用类型。值类型就是保存的时候值和类型放在同一块内存空间里面。而引用类型则是通过存放指针,然后指针指向另外一个内存空间。

下面图示中我们声明了两个变量i,j.当你改变i的值后,j的值不会随之改变。这种类型的数据就是值类型。



下面图示中我们声明两个变量obj,obj1,当我们改变obj的值后。ojb1的值也会随之改变。这种类型的数据是引用类型。



.net中的引用类型和值类型

  下面的图示中指出了除了String类型和Object类型是引用类型以外,其他的都是值类型。



装箱和拆箱

  恭喜你!一下子就学了这么多知识。但是在实际的工作中我们如果运用这些知识呢?我们碰到最多的就是把一个栈的数据移动到堆中或者把堆中的数据移到栈中!

  当我们需要把一个值类型的数据转换成引用类型的数据时,就需要把栈的数据移动到堆中。当我们需要把一个引用类型的数据转换成值类型的时候,就需要把堆中的数据移动到栈中。

  像这样把一个值类型转换成引用类型的操作称为:装箱(Boxing),相反则为拆箱(UnBoxing).



  如果使用ILDASM查看IL代码,其结果如下:



装箱和拆箱的性能问题

  为了测出装箱和拆箱的性能,我们对两段代码重复执行10W次,并且计算其所消耗的时间。一段代码是执行装箱操作,其花费了3542毫秒。另外一段代码是不需要执行装箱操作,其花费了2477毫秒。



  我没有做拆箱的性能测试,大家可以用stopwatch类来测算。

(备注:堆内存分配方式不是我上面讲的基于链式存储结构,而是有点类似栈的结构,详细请查看VIA CLR C#垃圾回收机制的部分)

原文链接

http://www.codeproject.com/Articles/76153/Six-important-NET-concepts-Stack-heap-value-types
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐