Stack vs. Heap: What's the difference?

http://translate.google.cn/translate?hl=zh-CN&sl=en&u=http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory01122006130034PM/csharp_memory.aspx&ei=90a8StaYCZnW7APixaTzCQ&sa=X&oi=translate&resnum=1&ct=result&prev=/search%3Fq%3DC%2523%2BHeap(ing)%2BVs%2BStack(ing)%2Bin%2B.NET%26hl%3Dzh-CN%26client%3Daff-maxthon%26channel%3Dchannel1%26hs%3Dor2%26affdom%3Dmaxthon.com%26newwindow%3D1

 

即使。NET框架 , 虽然我们没有积极地担心内存管理和垃圾收集(GC),我们仍然要牢记内存管理和GC,以优化我们的应用程序的性能。 Also, having a basic understanding of how memory management works will help explain the behavior of the variables we work with in every program we write.  In this article I'll cover the basics of the Stack and Heap, types of variables and why some variables work as they do. 另外,有一个怎样的内存管理工作将有助于解释的变量我们的工作与行为的基本理解在每个程序我们写。在这篇文章中我将介绍的栈和堆,变量类型以及为什么一些基本变量他们做工作。

There are two places the .NET framework stores items in memory as your code executes.  If you haven't already met, let me introduce you to the Stack and the Heap.  Both the stack and heap help us run our code.  They reside in the operating memory on our machine and contain the pieces of information we need to make it all happen. 有两个地方。NET框架的项目存储在内存中的代码执行。如果你还没有满足,让我向您介绍堆栈和堆。均栈和堆帮我们搞我们的代码。他们身居在我们的机器的内存并包含了我们需要的信息使这一切发生的部分。

Stack vs. Heap: What's the difference? 堆栈与堆:有什么区别?

The Stack is more or less responsible for keeping track of what's executing in our code (or what's been "called").  The Heap is more or less responsible for keeping track of our objects (our data, well... most of it - we'll get to that later.). 堆栈是或多或少负责保持的东西在我们执行跟踪代码(或什么是“叫”)。堆或多或少保持跟踪的对象负责(我们的数据,以及...大部分它-我们将稍后到达。)。

Think of the Stack as a series of boxes stacked one on top of the next.  We keep track of what's going on in our application by stacking another box on top every time we call a method (called a Frame).  We can only use what's in the top box on the stack.  When we're done with the top box (the method is done executing) we throw it away and proceed to use the stuff in the previous box on the top of the stack. 该堆栈看作一个堆叠下。我们随时会发生什么的堆叠另一个上面我们每次调用一个方法在我们的应用程序中(称为帧)。我们只能使用所谓的运动上衣1盒系列在堆栈上的机顶盒。当我们完成与机顶盒(该方法完成执行),我们把它扔掉并继续使用在对栈顶上框的东西。 The Heap is similar except that its purpose is to hold information (not keep track of execution most of the time) so anything in our Heap can be accessed at  any time.  With the Heap, there are no constraints as to what can be accessed like in the stack.  The Heap is like the heap of clean laundry on our bed that we have not taken the time to put away yet - we can grab what we need quickly.  The Stack is like the stack of shoe boxes in the closet where we have to take off the top one to get to the one underneath it. 堆但其目的是举办类似的信息(不保留执行跟踪大部分时间),以便在我们的堆什么问题都可以在任何时候访问随着堆。,以有没有什么可以像访问限制在栈中。堆就像是干净的衣物堆在我们的床上我们没有花时间去收拾但-我们可以抓住我们需要迅速。堆栈像鞋盒堆栈在衣柜里是我们要起飞前一去下方1人。

The picture above, while not really a true representation of what's happening in memory, helps us distinguish a Stack from a Heap. 上面的图片,而不是一个什么样的内存中发生的真正的代表性,帮助我们区分堆堆栈。

The Stack is self-maintaining, meaning that it basically takes care of its own memory management.  When the top box is no longer used, it's thrown out.  The Heap, on the other hand, has to worry about Garbage collection (GC) - which deals with how to keep the Heap clean (no one wants dirty laundry laying around... it stinks!). 堆栈是自我维持,这意味着它基本上是将自己的内存管理。机顶盒时不再使用,它扔掉。堆另一方面,要担心的垃圾收集(GC) -其中涉及如何保持堆干净(没有人愿意脏衣服乱扔...很臭!)。

What goes on the Stack and Heap? 怎么去?的栈和堆

We have four main types of things we'll be putting in the Stack and Heap as our code is executing: Value Types, Reference Types, Pointers, and Instructions. 我们有四个东西我们将在栈和堆将作为我们的代码执行:值类型,引用类型,指针和说明主要类型。

Value Types: 值类型:

In C#, all the "things" declared with the following list of type declarations are Value types (because they are from System.ValueType): 在C#中,所有的“东西”,同类型声明下面的列表中声明的值类型(因为它们是从System.ValueType):

  • bool 布尔
  • byte 字节
  • char 字符
  • decimal 十进制
  • double
  • enum 枚举
  • float 浮动
  • int 廉政
  • long 长的
  • sbyte sbyte
  • short 短的
  • struct 结构
  • uint 机组
  • ulong 乌龙
  • ushort ushort

Reference Types: 引用类型:

All the "things" declared with the types in this list are Reference types (and inherit from System.Object... except, of course, for object which is the System.Object object): 所有的“东西”,在此列表中的类型声明的引用类型(继承自System.Object ...当然除了,对象这是System.Object对象):

  • class
  • interface 接口
  • delegate 委托
  • object 对象
  • string 字符串

Pointers: 指针:

The third type of "thing" to be put in our memory management scheme is a Reference to a Type. 在“东西”第三类是在我们的记忆管理计划付诸表决是一个引用的类型。 A Reference is often referred to as a Pointer.  We don't explicitly use Pointers, they are managed by the Common Language Runtime (CLR). 阿参考通常称为指针。我们不明确地使用指针,他们的管理是由公共语言运行库(CLR)。 A Pointer (or Reference) is different than a Reference Type in that when we say something is a Reference Type is means we access it through a Pointer.  A Pointer is a chunk of space in memory that points to another space in memory.  A Pointer takes up space just like any other thing that we're putting in the Stack and Heap and its value is either a memory address or null. 一个指针(或参考)是不同于一个引用类型的当我们说几句话是引用类型是意味着我们可以通过一个指针它。指针是在内存空间块它指向另一个内存空间。甲指针占就像任何其他的事情我们在栈和堆其价值将空间要么是一个内存地址或null。

Instructions: 说明:

You'll see how the  "Instructions" work later in this article... 您会看到“说明”工作本文稍后...

How is it decided what goes where? 如何决定去什么地方? (Huh?) (咦?)

Ok, one last thing and we'll get to the fun stuff. 好吧,最后一件事情我们会到达有趣的东西。

Here are our two golden rules: 以下是我们的两个黄金规则:

  1. A Reference Type always goes on the Heap - easy enough, right? 引用类型总是接着堆-很容易,对不对?

  2. Value Types and Pointers always go where they were declared.  This is a little more complex and needs a bit more understanding of how the Stack works to figure out where "things" are declared. 值类型和指针总是宣称他们在那里。这是一个稍微复杂需要多一点理解如何堆栈工程找出其中的“东西”的声明。

The Stack, as we mentioned earlier, is responsible for keeping track of where each thread is during the execution of our code (or what's been called).  You can think of it as a thread "state" and each thread has its own stack.  When our code makes a call to execute a method the thread starts executing the instructions that have been JIT compiled and live on the method table, it also puts  the method's parameters on the thread stack.  Then, as we go through the code and run into variables within the method they are placed on top of the stack.  This will be easiest to understand by example... 堆栈,正如我们前面提到的,是保持跟踪负责其中每个线程在我们执行代码是(或什么的被称为)。您可以把它作为一个线程“国家”,每个线程都有它自己的堆栈。当我们的代码使调用一个方法的执行线程开始执行已JIT编译和居住方法表的指示,它也对线程堆栈的方法的参数。然后,当我们经过代码并运行到他们是在对堆栈的顶部放置方法变量。这将是最容易理解的例子...

Take the following method. 看看下面的方法。

public int AddFive( int pValue) 公共 廉政 AddFive( 廉政 pValue)
{
int result; int结果;
result = pValue + 5; 结果= pValue + 5;
return result; 返回 结果;
}

Here's what happens at the very top of the stack.  Keep in mind that what we are looking at is placed on top of many other items already living in the stack: 以下是在栈的最高层发生。请记住我们所希望的是对已在许多生活堆栈上面放着其他项目:

Once we start executin ghte method, the method's parameters are placed on the stack (we'll talk more about passing parameters later). 一旦我们开始executin ghte方法,该方法的参数是放在栈上(我们将谈论以后的传递参数)。

NOTE : the method does not live on the stack and is illustrated just for reference.注意:该方法不居住在堆栈仅供参考说明。

Next, control (the thread executing the method) is passed to the instructions to the AddFive() method which lives in our type's method table, a JIT compilation is performed if this is the first time we are hitting the method. 接下来,控制(线程执行方法)被传递给指示AddFive()方法在我们的生命类型的方法表,一个JIT编译执行如果这是我们第一次打击的方法。

As the method executes, we need some memory for the "result" variable and it is allocated on the stack. 由于该方法执行时,我们需要一些“效果”变量的内存这是在堆栈上分配。

The method finishes execution and our result is returned. 该方法完成执行我们的结果返回。

And all memory allocated on the stack is cleaned up by moving a pointer to the available memory address where AddFive() started and we go down to the previous method on the stack (not seen here). 和所有的内存堆栈上分配的清洁通过移动指针到可用的内存地址AddFive()展开我们深入到堆栈上了以前的方法(没有看到这里)。

In this example, our "result" variable is placed on the stack.  As a matter of fact, every time a Value Type is declared within the body of a method, it will be placed on the stack. 在这个例子中,我们的“结果”变量是放在堆栈。作为事实上,每次值类型是在一个方法体宣布,将在堆栈上。

Now, Value Types are also sometimes placed on the Heap.  Remember the rule, Value Types always go where they were declared?  Well, if a Value Type is declared outside of a method, but inside a Reference Type it will be placed within the Reference Type on the Heap. 现在,值类型有时也被放置在堆。记住规则,值类型总是宣称他们在那里?那么,如果一个数值类型声明之外的方法,而是在一个引用类型将放在内部参考在堆型。

Here's another example. 这里还有一个例子。

If we have the following MyInt class (which is a Reference Type because it is a class): 如果我们有以下明特类(这是一个引用类型因为它是一个类):

public class MyInt 公共类
{
public 公众 int MyValue; 廉政 MyValue;
}

and the following method is executing: 而下面的方法是执行:

public MyInt AddFive( int pValue) 公共 敏AddFive( 廉政 pValue)
{
MyInt result = new MyInt(); 敏结果= 敏();
result.MyValue = pValue + 5; result.MyValue = pValue + 5;
               
return result; 返回 结果;
}

Just as before, the thread starts executing the method and its parameters are placed on sthe thread's stack. 正如以前一样,线程开始执行的方法和它的参数是对sthe线程的堆栈上。

Now is when it gets interesting... 现在是当它获取有趣...

Because MyInt is a Reference Type, it is placed on the Heap and referenced by a Pointer on the Stack. 因为敏是引用类型,它是放在堆和1指针引用的堆栈。

After AddFive() is finished executing (like in the first example), and we are cleaning up... 经过AddFive()是执行完毕(如在第一个例子),我们正在清理...

we're left with an orphaned MyInt in the heap (there is no longer anyone in the Stack standing around pointing to MyInt)! 我们留下了一个孤儿在堆明特(没有周围指向堆栈站在长敏人)!

This is where the Garbage Collection (GC) comes into play.  Once our program reaches a certain memory threshold and we need more Heap space, our GC will kick off.  The GC will stop all running threads (a FULL STOP), find all objects in the Heap that are not being accessed by the main program and delete them.  The GC will then reorganize all the objects left in the Heap to make space and adjust all the Pointers to these objects in both the Stack and the Heap.  As you can imagine, this can be quite expensive in terms of performance, so now you can see why it can be important to pay attention to what's in the Stack and Heap when trying to write high-performance code. 这就是垃圾收集(GC)发挥作用的地方。一旦我们的计划达到一定内存阈值我们需要更多的堆空间,我们的GC将揭开序幕。GC将停止所有正在运行的线程(句号),找到的所有对象在那些不被访问的主要程序并将其删除堆。GC将所有的重组然后在左边堆对象使空间和调整所有的指针都堆栈和堆这些对象。正如你可以想象,这可能是非常昂贵性能方面,现在您就可以明白为何重要的是要注意什么堆栈和堆的当试图编写高性能的代码。

Ok... 玉... That great, but how does it really affect me? 伟大的,但它如何真正影响到我吗?

Good question. 好问题。

When we are using Reference Types, we're dealing with Pointers to the type, not the thing itself.  When we're using Value Types, we're using the thing itself.  Clear as mud, right? 当我们使用引用类型,我们处理的类型指针,而不是事物本身。当我们使用值类型,我们使用的事物本身。泥土清除,对不对?

Again, this is best described by example. 再次,这是最好的描述的例子。

If we execute the following method: 如果我们执行下面的方法:

public int ReturnValue() 公共廉政 ReturnValue()
{
int x = new int (); 廉政 x = 新国际 ();
x = 3; x = 3;
int y = new int (); 廉政 y二新国际 ();
y = x; ý = X信息;
y = 4; ý = 4;
return x; 回报×;
}

We'll get the value 3.  Simple enough, right? 我们将得到价值3。是不是很简单吗?

However, if we are using the MyInt class from before 然而,如果我们使用的是类从之前敏

public class MyInt 公共
{
               
public 公众 int MyValue; 廉政 MyValue;
}

and we are executing the following method: 我们执行下面的方法:

public int ReturnValue2() 公共廉政 ReturnValue2()
{
MyInt x = new MyInt(); 明特正确x = new敏();
x.MyValue = 3; x.MyValue = 3;
MyInt y = new MyInt(); 明特y二敏();
y = x; ý = X信息;
y.MyValue = 4; y.MyValue = 4;
return x.MyValue; 返回 x.MyValue;
}

What do we get?...    4! 我们得到什么?... 4!

Why?...  How does x.MyValue get to be 4?... 为什么呢?...如何x.MyValue获得为4?... Take a look at what we're doing and see if it makes sense: 看看我们在做什么研究看看它是否有道理:

In the first example everything goes as planned: 在第一个例子一切按计划进行:

public int ReturnValue() 公共廉政 ReturnValue()
{
int x = 3; 廉政 x = 3;
int y = x; 廉政 ý = X信息;
y = 4; ý = 4;
return x; 回报×;
}

In the next example, we don't get "3" because both variables "x" and "y" point to the same object in the Heap. 在接下来的例子中,我们没有得到“3”,因为这两个变量的“X”和“y”点在堆相同的对象。

public int ReturnValue2() 公共廉政 ReturnValue2()
{
MyInt x; 明特x;
x.MyValue = 3; x.MyValue = 3;
MyInt y; 明特ý;
y = x; ý = X信息;
y.MyValue = 4; y.MyValue = 4;
return x.MyValue; 返回 x.MyValue;
}

Hopefully this gives you a better understanding of a basic difference between Value Type and Reference Type variables in C# and a basic understanding of what a Pointer is and when it is used.  In the next part of this series, we'll get further into memory management and specifically talk about method parameters. 希望这个给你一之间的价值类型和引用类型在C变量的根本区别更好地了解#和对什么是指针是基本的了解和使用时。在本系列的下一部分,我们将进一步进入内存管理和具体谈谈方法的参数。

For now... 现在...

Happy coding. 快乐编码。

Part I | Part II | Part III | Part IV第一部分| 第二部分 | 第三部分 | 第四部分

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值