引用类型和值类型在方法调用中的异同?
2005-09-26 13:25
190 查看
刚才在CSDN上有一篇很hot的帖子,地址: http://community.csdn.net/Expert/topic/4292/4292562.xml?temp=.4954492 搞得我也甚是头晕
,因为对JIT编译器的内部运作情况还真是不了解,这里先简单说下我的想法.
先简单说下值类型和引用类型的区别:
1.值类型在栈上分配,定义了一个貌似Int32 i=123 这样的值变量之后,i 变量包含的是123这个实体,不包含地址值,但是刚才也有人说i其实也是在栈上有地址的---栈地址,这点我也认同.
2.引用类型: 引用类型是在托管堆上分配的,貌似这样的 Object o=new Object(); 编译器看到这一句以后,先在托管堆上分配给一块连续的内存用于包含“值”实体内容,至于还分配了方法表的指针和一个SyncBlockIndex,那是后话.然后就是把这块内存地址返回给o保存.
下面来说说方法调用的情况:
1.没有ref或out限制,参数为值类型,这没什么好说的,也就是把栈上的实体内容深拷贝到虚参里去,从而不对原来的实参构成影响.
2.有ref或out限制,虚参为引用类型,也没什么好说的,传递的是引用参数保存的内存地址。
------------------------------------------
3.像这样的调用
public static void change(ref Int32 newi)//实参为Int32 oldi
很明显,实参oldi是一个值类型,不能储存地址,储存的是实体本身。
在change方法中,参数ref Int32 newi实际上也是申明了一个新的变量,因为前面有ref限制了,我的看法是:编辑器看到这个ref关键词以后,可以看到il代码中,这里的写法实际上是Int32 & ,按照C++的观点,是用newi这个地址(因为有&修饰)去指向oldi包含的实体内容。
所以,我的假想认为编译器在这里的做法就是:告诉newi这个地址去指向oldi的实体,在方法调用完毕之后,因为change方法已经把内存中oldi包含的实体改变了,所以再WriteLine的时候,就得到了新值!
4.像这样的调用
public static void change(Object newo)//实参为Object oldo
这里用的是传值调用,参数是引用类型。
newo是一个地址值,保存的new obj后返回的内存地址。
我在这里的假想是:编译器的做法是把oldo的地址拷贝过来以后,因为newo是一个新定义的引用变量,编译器就告诉newo,只是取出oldo指向内存的实体,并且返回一个新的地址给newo,而不要又指向原来oldo保存的原始内存地址。
当调用完毕之后,因为是新的内存地址,所以对原来的没有影响。
------------------------------
这些是我的假设,各位不知道有没有看法?
,因为对JIT编译器的内部运作情况还真是不了解,这里先简单说下我的想法.
先简单说下值类型和引用类型的区别:
1.值类型在栈上分配,定义了一个貌似Int32 i=123 这样的值变量之后,i 变量包含的是123这个实体,不包含地址值,但是刚才也有人说i其实也是在栈上有地址的---栈地址,这点我也认同.
2.引用类型: 引用类型是在托管堆上分配的,貌似这样的 Object o=new Object(); 编译器看到这一句以后,先在托管堆上分配给一块连续的内存用于包含“值”实体内容,至于还分配了方法表的指针和一个SyncBlockIndex,那是后话.然后就是把这块内存地址返回给o保存.
下面来说说方法调用的情况:
1.没有ref或out限制,参数为值类型,这没什么好说的,也就是把栈上的实体内容深拷贝到虚参里去,从而不对原来的实参构成影响.
2.有ref或out限制,虚参为引用类型,也没什么好说的,传递的是引用参数保存的内存地址。
------------------------------------------
3.像这样的调用
public static void change(ref Int32 newi)//实参为Int32 oldi
很明显,实参oldi是一个值类型,不能储存地址,储存的是实体本身。
在change方法中,参数ref Int32 newi实际上也是申明了一个新的变量,因为前面有ref限制了,我的看法是:编辑器看到这个ref关键词以后,可以看到il代码中,这里的写法实际上是Int32 & ,按照C++的观点,是用newi这个地址(因为有&修饰)去指向oldi包含的实体内容。
所以,我的假想认为编译器在这里的做法就是:告诉newi这个地址去指向oldi的实体,在方法调用完毕之后,因为change方法已经把内存中oldi包含的实体改变了,所以再WriteLine的时候,就得到了新值!
4.像这样的调用
public static void change(Object newo)//实参为Object oldo
这里用的是传值调用,参数是引用类型。
newo是一个地址值,保存的new obj后返回的内存地址。
我在这里的假想是:编译器的做法是把oldo的地址拷贝过来以后,因为newo是一个新定义的引用变量,编译器就告诉newo,只是取出oldo指向内存的实体,并且返回一个新的地址给newo,而不要又指向原来oldo保存的原始内存地址。
当调用完毕之后,因为是新的内存地址,所以对原来的没有影响。
------------------------------
这些是我的假设,各位不知道有没有看法?
相关文章推荐
- 问题(怎样在dephi中引用.net中定义的类.方法参数,参数类型为XMLdocument?我要调用此方法并把实例花的xmldocument类型的变量作为参数给它。)
- java泛型反映调用方法体内类型引用问题
- 被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法
- 调用可能未定义的方法 attachVideo (通过 static 类型 flash.media:Video 引用)解决办法
- 关于实现引用类型数组去调用引用类的方法的问题的解决
- 17.2015.08.04第十八节课 C#2 (数值类型及调用、引用类型及调用、装拆箱、常量、变量、数据类型转换、算术运算符、赋值运算符、关系运算符、逻辑运算符、字符串的常用方法)
- Flex错误1061:调用可能未定义的方法 (通过 static 类型 Class 引用)
- 反射技术动态调用方法中的引用类型参数传递 (转)
- flex 3 list控件添加Item的方法【1061: 调用可能未定义的方法 addItem (通过 static 类型 spark.components:List 引用)】
- 类型:JQuery;问题:ajax调用ashx文件;结果:ashx文件怎么获取$.ajax()方法发送的json数据
- 《CLR via C#》精髓:引用类型和值类型
- 类型,对象,线程栈,托管堆在运行时的关系,以及clr如何调用静态方法,实例方法,和虚方法
- C#类和接口、虚方法和抽象方法及值类型和引用类型的区别(转)
- JavaSE8基础 多态 子类重写了父类的普通方法 父类引用调用子类中重写的方法
- C#反射得并调用方法(方法参数类型)
- java调用.netwebservice的方法,返回类型为XmlDocument
- Error:(95, 74) 警告: 最后一个参数使用了不准确的变量类型的 varargs 方法的非 varargs 调用; 对于 varargs 调用, 应使用 Class<?> 对于非 varar
- 引用类型和值类型
- [VB.NET]引用和值类型的区别? 分不清了,麻烦大家看看我的代码.
- 微信开发三 使用反射根据消息类型自动调用不同方法