西安网站建设优化与推广,整合营销名词解释,物业公司网站建设方案,企业官网快速建站框架前言 虽然在.Net Framework 中我们不必考虑内在管理和垃圾回收(GC)#xff0c;但是为了优化应用程序性能我们始终需要了解内存管理和垃圾回收(GC)。另外#xff0c;了解内存管理可以帮助我们理解在每一个程序中定义的每一个变量是怎样工作的。 简介 这篇文章我们将介绍一些方…前言 虽然在.Net Framework 中我们不必考虑内在管理和垃圾回收(GC)但是为了优化应用程序性能我们始终需要了解内存管理和垃圾回收(GC)。另外了解内存管理可以帮助我们理解在每一个程序中定义的每一个变量是怎样工作的。 简介 这篇文章我们将介绍一些方法参数传递行为在堆与栈中的影响。前几节我们介绍了堆与栈的基本工作原理程序执行时值类型与引用类型在堆栈中的存储。另外我们已经介绍了一些关于指针的基本知识。这一节中参数传递对堆栈的影响很重要下面会慢慢道来。 参数大画面
下面是当代码运行时会产生的一个详细过程。上几节已经介绍过当一个方法被调用时会产生的基本情况让我们来看一下更加详细的内容。
当我们调用一个方法时会发生以下情形
栈会分配一块内存空间给程序执行所需要的信息(我们叫它栈结构Stack Frame)。一个栈结构包含方法调用地址(指针)它以一个GOTO指令的形式存在栈里。因此当程序执行完方法(method)时它会知道怎么样返回进而曳继续执行代码。方法的所有参数将被复制到栈里这是我们将要更加详细介绍的部分。控制被传递到JIT编译过的方法里同时线程开始执行代码。此时我们将有另一个方法呈现在栈结构的“回调栈”里。
代码 public int AddFive(int pValue) { int result; result pValue 5; return result; } 栈像下图所示 注意ReturnValue方法不会存在栈上图中把ReturnValue作为此栈结构的开始只是为了解释栈原理。 像前几节介绍的值类型和引用类型在栈里的存储是不同的。栈为任何值类型创建副本栈也为任何引用类型的指针创建副本。 值类型传递
下面是值类型传递在栈里的内幕。 首先当我们传递一个值类型变量时栈会为它分配一块内存空间并把值类型变量的值存储进去。看下面的代码 class Class1 { public void Go() { int x 5; AddFive(x); Console.WriteLine(x.ToString()); } public int AddFive(int pValue) { pValue 5; return pValue; } } 当代码执行时栈为x分配一块内存空间并存储值5 然后AddFive()被放到栈上同时栈分配内存空间给参数pValue并复制x的值给它。 当AddFive()执行完成线程被传递回Go()。同时因为AddFive()执行完它的参数pValue也实质上被移除。 所以结果是5是合理的。关键点是任何被传递的值类型参数仅是一个碳复制因为我们希望保护原始变量的值。
有一点要记住的是如果我们有一个非常庞大的值类型(如庞大的struct类型)传递到栈里当处理器循环复制它并循环占有栈空间时将会非常耗资源。栈没有无限的空间去使用就像用水杯不断的接水早晚会溢出一样。Struct类型可以变得非常庞大我们要小心并清醒的使用它。 下面是一个比较大的struct结构类型 public struct MyStruct { long a, b, c, d, e, f, g, h, i, j, k, l, m; } 让我们看看执行下面代码Go()方法时再到DoSomething()方法会发生的情况 public void Go() { MyStruct x new MyStruct(); DoSomething(x); } public void DoSomething(MyStruct pValue) { // 省略具体实现.... } 这可能会非常低效。想像一下如果我们传递MyStruct几千次它会怎么样让程序死掉。 那么我们怎么才能回避这样的问题呢那就是仅传递原始值类型的引用。
public void Go() { MyStruct x new MyStruct(); DoSomething(ref x); } public struct MyStruct { long a, b, c, d, e, f, g, h, i, j, k, l, m; } public void DoSomething(ref MyStruct pValue) { // 省略实现.... } 这样就能节省内存并提升内存使用效率 唯一需要注意的是传递引用时我们在访问原始变量x的值任可对pValue的改变都会影响到x。
下面的代码会将x改变成12345因为pValue.a实际上指向原始x声明时所在的内存地址。 public void Go() { MyStruct x new MyStruct(); x.a 5; DoSomething(ref x); Console.WriteLine(x.a.ToString()); } public void DoSomething(ref MyStruct pValue) { pValue.a 12345; } 未完待续。。。 翻译 http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory2B01142006125918PM/csharp_memory2B.aspx