深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第三节 栈与堆,值类型与引用类型

转载 2013年12月05日 10:45:45

前言


虽然在.Net Framework 中我们不必考虑内在管理和垃圾回收(GC),但是为了优化应用程序性能我们始终需要了解内存管理和垃圾回收(GC)。另外,了解内存管理可以帮助我们理解在每一个程序中定义的每一个变量是怎样工作的。


简介


本文将介绍值类型与引用类型在堆栈里的基本存储原理。

值类型会存储在堆里?


是的,值类型有时候就是会存储在堆里。上一节中介绍的黄金规则2:值类型和指针永远存储在它们声明时所在的堆或栈里。如果一个值类型不是在方法中定义的,而是在一个引用类型里,那么此值类型将会被放在这个引用类型里并存储在堆上。

代码图例


我们定义一个引用类型:
[csharp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public class MyInt  
  2.           {            
  3.              public int MyValue;  
  4.           }  

里面包含一个值类型MyValue。
执行下面的方法:
[csharp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public MyInt AddFive(int pValue)  
  2.           {  
  3.                 MyInt result = new MyInt();  
  4.                 result.MyValue = pValue + 5;  
  5.                 return result;  
  6.           }  

就像上一节介绍的一样,线程开始执行此方法,参数pValue将会被放到当前线程栈上。


接下来不同于上一节所介绍的是MyInt是一个引用类型,它将被放到堆上并在栈上放一个指针指向它在堆里的存储。


当AddFive()执行完成后,如上一节所讲栈开始清理。

现在是需要C#垃圾回收GC的时候了。当我们的程序所占内存到达临界值时(即将溢出),我们会需要更多的堆空间,GC就会开始运行。GC停止所有当前运行线程(整体停止),找到堆里所有主程序不会访问到的对象并删除它们。然后,GC会识别所有堆里剩下的对象并分配内存空间给它们,同时调整堆和栈里指向它们的指针。你可以想像这是非常耗资源的,这会影响到程序的性能。这就是为什么我们需要理解和注意堆栈的使用,进而写出高性能代码。

堆栈原理对代码的影响


当我们使用引用类型时,我们在和指向引用类型的指针打交道,而不是引用类型本身。
当我们使用值类型时,我们就是在和值类型本身打交道。

代码图例


假设执行方法:
[csharp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public int ReturnValue()  
  2.           {  
  3.                 int x = new int();  
  4.                 x = 3;  
  5.                 int y = new int();  
  6.                 y = x;        
  7.                 y = 4;            
  8.                 return x;  
  9.           }  

我们会得到值 3


使用引用类型:
[csharp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public class MyInt  
  2.           {  
  3.                 public int MyValue;  
  4.           }  


如果执行方法:
[csharp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public int ReturnValue2()  
  2. {  
  3.       MyInt x = new MyInt();  
  4.       x.MyValue = 3;  
  5.       MyInt y = new MyInt();  
  6.       y = x;                   
  7.       y.MyValue = 4;                
  8.       return x.MyValue;  
  9. }  

我们得到的值是4而不是3!(译外话:这是很简单,但相信还是有很多人不知道原理的)

第一个示例中:
[csharp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public int ReturnValue()  
  2.           {  
  3.                 int x = 3;  
  4.                 int y = x;      
  5.                 y = 4;  
  6.                 return x;  
  7.           }  



x就是3,y就是4。操作两个不同对象。

第二个示例:
[csharp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public int ReturnValue2()  
  2.           {  
  3.                 MyInt x;  
  4.                 x.MyValue = 3;  
  5.                 MyInt y;  
  6.                 y = x;                  
  7.                 y.MyValue = 4;  
  8.                 return x.MyValue;  
  9.           }  


得到的值是4不是3是因为我们操作栈里两个指针并且它们指向堆里同一个对象。


总结


希望这篇文章能帮助你更好的理解值类型变量与引用类型变量的不同,同时理解什么是指针,什么时候用到指针。以后的文章里会更深入的介绍C#内存管理并详细阐述方法参数。

翻译于:http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory01122006130034PM/csharp_memory.aspx

相关文章推荐

深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第五节 引用类型复制问题及用克隆接口ICloneable修复

虽然在.Net Framework 中我们不必考虑内在管理和垃圾回收(GC),但是为了优化应用程序性能我们始终需要了解内存管理和垃圾回收(GC)。另外,了解内存管理可以帮助我们理解在每一个程序中定义的...

深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第六节 理解垃圾回收GC,提搞程序性能

虽然在.Net Framework 中我们不必考虑内在管理和垃圾回收(GC),但是为了优化应用程序性能我们始终需要了解内存管理和垃圾回收(GC)。另外,了解内存管理可以帮助我们理解在每一个程序中定义的...

深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第四节 参数传递对堆栈的影响 1

虽然在.Net Framework 中我们不必考虑内在管理和垃圾回收(GC),但是为了优化应用程序性能我们始终需要了解内存管理和垃圾回收(GC)。另外,了解内存管理可以帮助我们理解在每一个程序中定义的...

深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第一节 理解堆与栈

简介 虽然在.Net Framework 中我们不必考虑内在管理和垃圾回收(GC),但是为了优化应用程序性能我们始终需要了解内存管理和垃圾回收(GC)。另外,了解内存管理可以帮助我们理解在每一个程序中...

深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第二节 栈基本工作原理

虽然在.Net Framework 中我们不必考虑内在管理和垃圾回收(GC),但是为了优化应用程序性能我们始终需要了解内存管理和垃圾回收(GC)。另外,了解内存管理可以帮助我们理解在每一个程序中定义的...

unity3d中两种语言的对比JavaScript vs C# 第三节

系列教程的第三节,此节教程主要通过一段具体的功能代码来比较在unity3d中所使用的两种程序语言的区别,下面是原文: This is the third part of a series that ...

c++中堆和栈的的区别(stack vs heap)

 堆和栈的区别 一、预备知识—程序的内存分配 一个由c/C++编译的程序占用的内存分为以下几个部分 1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操...
  • hyqsong
  • hyqsong
  • 2014年12月18日 15:57
  • 2457

第三节:原生数据类型使用陷阱 Pitfall of Primitive Data Type

1.Java中的原生数据类型共有8种: 1)整型:使用int表示(32位)。2)字节型:使用byte表示(表示-128~127之间的256个整数)。3)短整型:使用short表示(16位)。4)长整型...
  • lwlgkg
  • lwlgkg
  • 2011年04月26日 12:00
  • 345

初识java的面向对象及Java中数据类型-----自学JAVA(第三节)

本文属于小编原创,请使用者标明出处: 一、结构化         顺序结构(从上往下依次执行);         选择结构(包括单选择、双选择、多选择),if语句和switch语句;         ...

图解C#的值类型,引用类型,栈,堆,ref,out

C# 的类型系统可分为两种类型,一是值类型,一是引用类型,这个每个C#程序员都了解。还有托管堆,栈,ref,out等等概念也是每个C#程序员都会接触到的概念,也是C#程序员面试经常考到的知识,随便搜搜...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第三节 栈与堆,值类型与引用类型
举报原因:
原因补充:

(最多只允许输入30个字)