首页 新闻 会员 周边

请教一下关于ref和out的问题?

0
悬赏园豆:5 [已解决问题] 解决于 2010-08-16 11:16

代码如下:
int i = 0;
Test(out i);
void Test(out j)
{
  j = 4;
}
调用Test()方法时,变量i是不是会发生装箱操作呢,然后i和j同时指向相同的堆内存地址,是这样吗?参数用ref修饰时,也跟out一样会装箱吗?

在看看下面一个问题:
我首先自定义了一个Person类
public class Person
{
    public int age;
    public Person() { }
    public Person(int age)
    {
        this.age = age;
    }
}
public class Test
{
    public static void Main()
    {
        Person p1 = new Person();
        p1.age = 20;
        Change(ref p1);
        Console.Write(p1.age);
        Console.ReadLine();
    }
    static void Change(ref Person p2)
    {
        p2 = new Person(30);
    }
}
这段结果的输出结果为30,我有个疑问,在还未执行p2 = new Person(30)之前,我知道p1和p2同时指向一块堆内存,但当执行p2 = new Person(30)后,p2从新指向了新分配的内存,而p1还是指向原来的,如果按我这种思路的话,输出结果应该为20,怎么会是30呢?请高手指教,我内存方面哪个地方分析错了?谢谢!

yixin841210的主页 yixin841210 | 小虾三级 | 园豆:1138
提问于:2010-08-10 15:59
< >
分享
最佳答案
0

ref /out 使用的场景差不多。但是也有不同。ref是传递内存地址。out虽然也是传递内存地址。但是在进入方法体后会有初始化的操作。

void sum(out int intVal)
{ intVal=0;
int a=10
intVal+=a

}

如果调用传值 10 的话,intVal进入后必须初始化。

而用ref的话,是20。保留了原来的值。

收获园豆:5
邢少 | 专家六级 |园豆:10926 | 2010-08-10 16:42
那out/ref的时候如果是值类型会装箱吗?
yixin841210 | 园豆:1138 (小虾三级) | 2010-08-10 17:08
@yixin841210: 不会。它传递一个内存地址
邢少 | 园豆:10926 (专家六级) | 2010-08-11 08:35
@yixin841210: 你的问题中。ref 传递参数。传递的内存地址。然后你在change中又对改变量初始化了。初始化重新分配内存。这时候你的内存地址可能变了。你的最终输出值是30。 你的p2 就是你的p1 因为你把p1传递给了change.p2只是在change里的名称而已
邢少 | 园豆:10926 (专家六级) | 2010-08-11 08:40
其他回答(4)
0

很久很久以前我学VB的时候,老师教我们形参和实参。。。之后就没了    呵呵

like%'远远'% | 园豆:635 (小虾三级) | 2010-08-10 16:07
呵呵,看来你也得深入研究一下了啊
支持(0) 反对(0) yixin841210 | 园豆:1138 (小虾三级) | 2010-08-10 16:10
0

如果不带ref的话就是20,带了ref的话就是30.带了ref是传址的,所以new Person(30)时,实际已经改变了p1的引用.

I,Robot | 园豆:9783 (大侠五级) | 2010-08-10 16:24
不太明白啊,可否在详细解释一下,加ref修饰时在内存当中p2指向谁了啊,是指向跟p1一样的堆空间吗,还是指向其他?
支持(0) 反对(0) yixin841210 | 园豆:1138 (小虾三级) | 2010-08-10 16:52
0

    static void Change(ref Person p2)
    {
        p2 = new Person(30);
    }

这里的p2指向的就是p1,而你这边写了 new Person(30);,相当于p1=new Persion(30);

所以就是更改了P1,所以是30

kyo-yo | 园豆:5587 (大侠五级) | 2010-08-10 16:32
不太明白啊,可否在详细解释一下,加ref修饰时在内存当中p2指向谁了啊,是指向跟p1一样的堆空间吗,还是指向其他?
支持(0) 反对(0) yixin841210 | 园豆:1138 (小虾三级) | 2010-08-10 16:51
@yixin841210:引用类型,加不加 ref 都一样(string除外),传递的是 p1 的地址(一个32或64位整数,)
支持(0) 反对(0) Launcher | 园豆:45045 (高人七级) | 2010-08-10 17:02
@Galactica:那你的意思是加不加ref结果都是一样的啊?反正都是传递的P1的地址,是吗?可是不加的话结果是不一样的
支持(0) 反对(0) yixin841210 | 园豆:1138 (小虾三级) | 2010-08-10 17:11
@yixin841210:因为你在函数内使用了new,该操作会新分配一个地址,p2就会指向这个新的地址,出了函数作用域后,p2就会回收了,使用ref关键后,你的赋值操作符号 = 之后,会有一个拷贝构造函数,会把new对象的值拷贝进p2原来的地址空间去。
支持(0) 反对(0) Launcher | 园豆:45045 (高人七级) | 2010-08-10 17:53
结合楼上说的你自己可以测试下,在Change方法中如果不使用NEW,ref,而直接更改age,然后再打印值已经发生改变了,因为class对象本来就是引用类型,如果你传的不是类对象,而是具体的值将不会发生改变
支持(0) 反对(0) kyo-yo | 园豆:5587 (大侠五级) | 2010-08-11 12:36
0

你用了 ref 来指定参数,Change 方法传入的是p2指针,当 p2 = new Person(30); 后,p2(函数外为p1) 的指针地址发生了变化,指向了30那个位置,所以为30.

如果你 Change 方式是

static void Change(Person p2)

则输出仍然是20. 因为这是传入的是 p1 的指针的拷贝而不是指针本身,所以虽然其拷贝的指针p2地址指向了30那个位置,函数外那个p1 的指针地址却没有变。

eaglet | 园豆:17139 (专家六级) | 2010-08-11 07:47
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册