打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

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

参数传递对堆栈的影响

导航

前言


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

简介


继续上篇未完成的“参数传递对堆栈的影响”。

引用类型传递


传递引用类型跟上一节所示例中用引用的方式传递值类型相似。

如果使用引用类型(原文可能笔误,写的是值类型):
[csharp] view plain copy
  1. public class MyInt  
  2.            {  
  3.                public int MyValue;  
  4.            }  

然后调用Go()方法,MyInt会被放到堆里因为它是一个引用类型。
[csharp] view plain copy
  1. public void Go()  
  2.           {  
  3.              MyInt x = new MyInt();                
  4.           }  



如果执行下面代码中的Go():
[csharp] view plain copy
  1. public void Go()  
  2.           {  
  3.              MyInt x = new MyInt();  
  4.              x.MyValue = 2;  
  5.    
  6.              DoSomething(x);  
  7.    
  8.              Console.WriteLine(x.MyValue.ToString());  
  9.                 
  10.           }  
  11.    
  12.            public void DoSomething(MyInt pValue)  
  13.            {  
  14.                pValue.MyValue = 12345;  
  15.            }  

会发生这种情况:


  1. 开始调用Go(),栈分配一块内存空间给x。
  2. 执行行到DoSomething(),栈分配一块内在空间给pValue。
  3. x的值是堆中MyInt对应在栈里的内存地址,复制x给pValue。
因此,我们用pValue改变MyInt的MyValue的值时,x最终也会获得这个改变的值"12345“。
如果我们用引用的方式传递一个引用类型变量呢?

用引用的方式传递引用类型

我们有一个类Thing, 类Animal和Vegetables衍生于Thing:
[csharp] view plain copy
  1. public class Thing  
  2.            {  
  3.            }  
  4.    
  5.            public class Animal:Thing  
  6.            {  
  7.                public int Weight;  
  8.            }  
  9.    
  10.            public class Vegetable:Thing  
  11.            {  
  12.                public int Length;  
  13.            }  

执行下面的Go()方法:
[csharp] view plain copy
  1. public void Go()  
  2.           {  
  3.              Thing x = new Animal();  
  4.              
  5.              Switcharoo(ref x);  
  6.    
  7.               Console.WriteLine(  
  8.                 "x is Animal    :   "  
  9.                 + (x is Animal).ToString());  
  10.    
  11.               Console.WriteLine(  
  12.                   "x is Vegetable :   "  
  13.                   + (x is Vegetable).ToString());  
  14.                 
  15.           }  
  16.    
  17.            public void Switcharoo(ref Thing pValue)  
  18.            {  
  19.                pValue = new Vegetable();  
  20.            }  

x最终变成Vegetable。
打印结果:
[plain] view plain copy
  1. x is Animal    :   False  
  2. x is Vegetable :   True  

让我们看看堆栈里到底发生了什么情况


  1. 调用Go()方法,栈分配一块内存空间给x。
  2. 堆分配一块内存空间给Animal。
  3. 开始执行Switcharoo()方法,栈分配一块内存空间给pValue并指向x。

  4. 栈分配一块内存空间给Vegetable。
  5. pValue改变了x的值使其指向Vegetable的内在地址。
如果我们不是用ref传递的,打印结果正相反。


总结


我们已经演示了参数传递是怎么在内在中处理的。在接下来的文章里,存储在栈中的引用变量会产生什么情况以及怎么解决对象复制带来的问题。


翻译: http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory2B01142006125918PM/csharp_memory2B.aspx




本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
堆、栈和堆栈的区别
队列、堆、栈、堆栈的区别?
堆栈(stack)与堆(heap)的区别
一篇解释arm启动代码中最生涩隐晦地方的好文
ARM Cortex-M3的startup.s文件详解
19.1 详解startup_M051.s
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服