从赋值操作理解不同类型的函数传参

从赋值操作理解不同类型的函数传参

         我们都知道所谓的程序,就是对传入的数据进行操作,最终将处理的数据输出给用户。那么在我们的编程中的体现,就是通过函数(或者方法)参数传入数据,然后通过函数返回值输出处理后的数据。数据的传入涉及到函数的实参和形参的传递,数据的输出涉及到函数的返回值和返回值类型的参数。函数返回值没有什么特别之处,而其他的都是函数传参的问题,既然是传参,那么传参到底传过去了什么?

函数传参与赋值操作

         我们都知道函数传参涉及到形参和实参,那么实参和形参就是两个不同的变量,所以函数传参的过程,类似(或者说就是)使用实参给形参赋值的过程。那么我们先来分析按值传参的情况

         1是值类型变量的赋值操作图,我们大家都知道值类型变量直接保存变量的内容,所以赋值的过程就是将ValA保存的内容直接拷贝到ValB中,此时两个变量除了保存的值相同外,没有其他的任何关系,所以此时修改ValB的内容并不会引起ValA的变化。这是与值类型按值传参的效果是一样的。

1.值类型变量赋值

         2展示的是引用类型变量的赋值操作,我们都知道引用类型的变量保存的是一个地址,这个地址指向了变量内容所在的地址,也就是说引用变量保存的是一个地址。那么引用类型的赋值操作同样也是拷贝变量保存的内容,这样ValAValB就都指向了同样地址。如果我们修改ValB的成员,那么ValA中也会随之产生变化。我们可以看到值类型和引用类型的赋值操作是一样的,都是对变量直接保存的内容的拷贝过程。但是如果我们使用其他对象对ValB重新赋值,这时ValB就指向了其他对象,ValA还指向原来的对象并没有变化。

2.引用类型变量赋值

         我们知道C#中引入了ref关键字,使我们可以通过函数参数返回函数的处理结果,对于我们需要同时返回多项结果的时候比较有用。其实这也就是我们通常所说的按引用传参。图3展示了变量地址赋值操作,此时我们使用新的对象对ValB所指定的对象赋值,这是ValA也就指向了新的对象了。C#中的ref是否也是这样操作的呢?我们看以看一下下边的代码和相应的IL就知道了。

3.变量地址赋值操作

C#代码

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FunctionParameter
{
    class PassByValue
    {       
        public void PassValueParameterByReference(ref ReferencePara parameter)
        {
            parameter.a = 1;
            parameter = new ReferencePara();
        }

        public class ReferencePara
        {
            public int a;
            public int b;
        }
    }
}

 

对应的MSIL代码 

//传递的是变量的地址
.method public hidebysig instance void  PassValueParameterByReference(class FunctionParameter.PassByValue/ReferencePara& parameter) cil managed
{
  // 代码大小       17 (0x11)
  .maxstack  8
  IL_0000:  nop
  //加载参数
  IL_0001:  ldarg.1
  //加载对象的引用
  IL_0002:  ldind.ref
  IL_0003:  ldc.i4.1
  IL_0004:  stfld      int32 FunctionParameter.PassByValue/ReferencePara::a
  IL_0009:  ldarg.1
  IL_000a:  newobj     instance void FunctionParameter.PassByValue/ReferencePara::.ctor()
  //绑定对象的引用
  IL_000f:  stind.ref
  IL_0010:  ret
// end of method PassByValue::PassValueParameterByReference

总结

         从我们大学一开始接触计算机编程开始,我们就开始记忆两种函数传参的异同,其实传参的过程就是实参对形参赋值的过程,只不过有时拷贝的是变量的内容,有时拷贝的是变量的地址罢了。

posted @ 2012-06-21 01:43  无风听海  阅读(1310)  评论(2编辑  收藏  举报