让你一次性搞定堆、栈、值类型、引用类型-PartA[转]
.Net Framework 在执行代码时,有两个用来存储对象的地方,也就是堆和栈,用于帮助执行我们的代码。它们驻留在机器内存中,包含了所有我们需要实现的信息。
Stack VS Heap
栈多多少少用来负责跟踪你的代码里正在执行什么,或者说代码里的什么东东被called。而堆则或多或少用来跟踪我们的对象,或者说数据,大多数情况下都是数据啦——后头再详解。
上图虽然并不是真正的内存中堆栈的样子,不过有助于我们理解它们的区别。
What goes on the Stack and Heap?
值类型: c#中,值类型继承自System.ValueType:
bool, byte, char, decimal, double, enum, float, int, long, sbyte, short, struct, uint, ulong, ushort
引用类型:
而引用类型则有:
class, interface, delegate, object, string
指针:
内存管理模型中的第三种东东是对一个类型的引用。这个引用通常就是指指针。我们不能直接使用指针,它们被CLR所管理。指针不同于引用类型。当我们说某某是引用类型时,实际上就意味着我们要通过指针去访问这个类型的值。一个指针占用内存中的一块空间,指向内存中另外一块空间。指针跟任何别的放在堆栈中的东西一样,是要占用物理空间的。它的值要么是null,要么就是内存地址。
指令:
在后续文章中再解释,稍安勿躁……
How is it decided what goes where? (Huh?)
okok,再啰嗦两句我们就可以正式摆弄我们的堆栈了。
这里有两条黄金规则:
值类型以及指针,总是保存在其被声明(Declared)的地方。稍微复杂一丁点儿,因为需要理解什么是“其被声明的地方”
public int AddFive(int pValue)
{
int result;
result = pValue + 5;
return result;
}
让我们看看栈里头都发生了什么,记住我们看到的只是栈顶的东西,下头早有无数别的东东在里面了哦!
当我们开始执行这个方法时,方法的参数被压栈(稍后我们讨论参数传递)。
Notice: 方法并不存在stack里头,图例只是为了演示概念
下一步,控制(线程执行这个方法)被交给AddFive方法在方法表中的指令集,如果这是第一次使用这个方法,JIT编译将被执行。
在
方法结束了,result被返回。
这时栈顶指针将会移到最初AddFive方法开始的内存地址,这样所有刚才分配的内存空间都被清理掉了,然后接着执行AddFive更下面的函数(图中为显示)。
在这个例子里,result变量被压栈。事实上,任何时候值变量在方法内部被声明,都会被压栈。
在来一个例子:
如果我们有MyInt Class(引用类型):
public class MyInt
{
public int MyValue;
}
另外一个方法正在执行中:
public MyInt AddFive(int pValue)
{
MyInt result = new MyInt();
result.MyValue = pValue + 5;
return result;
}

AddFive执行完毕以后,我们开始清理栈顶:

这样我们就把MyInt对象当作孤儿留在了堆里头,因为栈中没有任何指针在引用它了!

这时候就是GC大显身手的时候啦!一旦我们
OK,好了好了,很棒很棒,不过,这东西到底会如何来折磨俺们呢?
好问题。
当我们使用引用类型时,我们实际上是使用指向该对象的指针,而不是对象本身。当我们使用值类型时,我们使用的就是值本身。清楚还是不清楚?
最好还是来个例子吧。public int ReturnValue()
{
int x = new int();
x = 3;
int y = new int();
y = x;
y = 4;
return x;
}
我们得到3,够简单吧。
如果这样呢:
public class MyInt
{
public int MyValue;
}
public int ReturnValue2()
{
MyInt x = new MyInt();
x.MyValue = 3;
MyInt y = new MyInt();
y = x;
y.MyValue = 4;
return x.MyValue;
}
那么我们将得到4。
为什么?
在第一个例子里所有事都按照预定计划行事:
public int ReturnValue()
{
int x = 3;
int y = x;
y = 4;
return x;
}

在后面的例子里,我们得不到3是因为x和y都指向堆里的同一个对象。
public int ReturnValue2()
{
MyInt x;
x.MyValue = 3;
MyInt y;
y = x;
y.MyValue = 4;
return x.MyValue;
}
希望本文能帮助您更好的理解值