英文出处:http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory2B01142006125918PM/csharp_memory2B.aspx
2009/12/4
19:00-20:40 看完部分一 速度有点慢,不过大致看懂了,金山词霸确实是个好东西```^_^
20:40--22:00(部分二) 才节约了20分钟,汗! 其实速度是有提高的,主要是人比较累了,容易走神,呵呵
这章太经典了,我有种要翻译此文的感觉,^_^
22:30 --23:15(部分三) 又节约了35分钟,不错,有进步!不过,只是大致看懂了,还需要细细的品,突然觉得
要翻译此文,有一定的难度了```` 觉得应该去看下中文的"深度复制"的资料````
23:15--23:42(部分三) 又看了一遍又觉得可以写了,呵呵
12/5
19:00-20:28(部分四) 部分四我想想还是先不要翻译了,先把前3个翻译再说
22:00 突然发现网上有翻译此文的文章,英文看完了才发现@#$#%@````,Ok现在转载过来吧,呵呵
再次感谢作者写这么好的文章,也感谢翻译此文的人,翻译的同意经典 专业
由于整理的比较麻烦, 第1 2 3 4部分我放在word里了:下载
尽管在.NET framework下我们并不需要担心内存管理和垃圾回收(Garbage Collection),但是我们还是应该了解它们,以优化我们的应用程序。同时,还需要具备一些基础的内存管理工作机制的知识,这样能够有助于解释我们日常程序编写中的变量的行为。在本文中我将讲解栈和堆的基本知识,变量类型以及为什么一些变量能够按照它们自己的方式工作。
在.NET framework环境下,当我们的代码执行时,内存中有两个地方用来存储这些代码。假如你不曾了解,那就让我来给你介绍栈(Stack)和堆(Heap)。栈和堆都用来帮助我们运行代码的,它们驻留在机器内存中,且包含所有代码执行所需要的信息。
* 栈vs堆:有什么不同?
栈负责保存我们的代码执行(或调用)路径,而堆则负责保存对象(或者说数据,接下来将谈到很多关于堆的问题)的路径。
可以将栈想象成一堆从顶向下堆叠的盒子。当每调用一次方法时,我们将应用程序中所要发生的事情记录在栈顶的一个盒子中,而我们每次只能够使用栈顶的那个盒子。当我们栈顶的盒子被使用完之后,或者说方法执行完毕之后,我们将抛开这个盒子然后继续使用栈顶上的新盒子。堆的工作原理比较相似,但大多数时候堆用作保存信息而非保存执行路径,因此堆能够在任意时间被访问。与栈相比堆没有任何访问限制,堆就像床上的旧衣服,我们并没有花时间去整理,那是因为可以随时找到一件我们需要的衣服,而栈就像储物柜里堆叠的鞋盒,我们只能从最顶层的盒子开始取,直到发现那只合适的。
以上图片并不是内存中真实的表现形式,但能够帮助我们区分栈和堆。
栈是自行维护的,也就是说内存自动维护栈,当栈顶的盒子不再被使用,它将被抛出。相反的,堆需要考虑垃圾回收,垃圾回收用于保持堆的整洁性,没有人愿意看到周围都是赃衣服,那简直太臭了!
* 栈和堆里有些什么?
当我们的代码执行的时候,栈和堆中主要放置了四种类型的数据:值类型(Value Type),引用类型(Reference Type),指针(Pointer),指令(Instruction)。
1.值类型:
在C#中,所有被声明为以下类型的事物被称为值类型:
2.引用类型:
所有的被声明为以下类型的事物被称为引用类型:
3.指针:
在内存管理方案中放置的第三种类型是类型引用,引用通常就是一个指针。我们不会显示的使用指针,它们由公共语言运行时(CLR)来管理。指针(或引用)是不同于引用类型的,是因为当我们说某个事物是一个引用类型时就意味着我们是通过指针来访问它的。指针是一块内存空间,而它指向另一个内存空间。就像栈和堆一样,指针也同样要占用内存空间,但它的值是一个内存地址或者为空。
4.指令:
在后面的文章中你会看到指令是如何工作的...
* 如何决定放哪儿?
这里有一条黄金规则:
1. 引用类型总是放在堆中。(够简单的吧?)
2. 值类型和指针总是放在它们被声明的地方。(这条稍微复杂点,需要知道栈是如何工作的,然后才能断定是在哪儿被声明的。)
就像我们先前提到的,栈是负责保存我们的代码执行(或调用)时的路径。当我们的代码开始调用一个方法时,将放置一段编码指令(在方法中)到栈上,紧接着放置方法的参数,然后代码执行到方法中的被“压栈”至栈顶的变量位置。通过以下例子很容易理解...
下面是一个方法(Method):
然后执行下面的方法:
就像前面提到的,方法及方法的参数被放置到 栈上,接下来,控制被传递到 堆栈中AddFive()的指令上。
我们将得到值3,很简单,对吧?
接着执行以下的方法: