3

我正在通过 C# 阅读 Jeffrey Richters CLR,在其中他说使用 ref 参数引用本身是按值传递的。这对我来说很有意义,并且似乎类似于指针。

即在C语言中,如果我将一个指针传递给一个函数,然后通过malloc分配指针,它会将指针更改为指向新的内存位置,但是我知道由于指针本身是一个副本,它不会重新分配原来的指针传入函数。为了完成对函数外部指针的更改,我必须使用双指针。

但是,在 C# 中:

void Swap(ref Object a, ref Object b)
{
    Object t = b;
    b = a;
    a =t ;
}

作品。这向我表明引用不是按价值计算的。与上面的 malloc 类似,我假设我可以通过引用传递一个对象并为其分配一个新对象,并且重新分配将在函数之外持续存在。

有人可以解决我的困惑吗?

4

3 回答 3

6

你有点偏了。对于引用类型引用按值传递的。传递ref参数是不同的。在

private void Frob(Foo foo) // Foo is a class
{

}

在调用站点对类型对象的引用的副本Foo被传递到方法Frob中。引用的这个副本是按值传递的。此引用和调用站点处的引用指向内存中的同一个对象,并将继续这样做,直到其中一个指向内存中的某个其他对象。例如,如果在这个方法里面,我们写

foo = someOtherFoo;

那么参数就不再是指与调用点的对象相同的对象了。呼叫站点参考没有改变

现在考虑我们是否引入ref关键字。

private void Frob(ref Foo foo)
{
    foo = someOtherFoo;
}

在这种情况下,foo是调用站点的变量的别名。这些变量不仅仅是指向内存中的同一个对象,就好像它们是同一个变量!foo这样一来,指向someOtherFoo不仅会foo在这个方法内部发生变化,这个变化也会反映在调用现场。

于 2011-04-29T03:20:22.867 回答
5

如果没有ref关键字,对象的引用是按值传递的。

使用ref关键字,对对象引用的引用按值传递。

[只是编译器隐藏了这样一个事实,即对显式传递的参数进行赋值ref正在更改指针]

于 2011-04-29T03:17:12.903 回答
0

当调用 this 传递原始指针值(引用)

void Swap(ref Object a, ref Object b)
{
    Object t = b;
    b = a;
    a = t;
}

这将传递原始指针的副本:

void Swap(Object a, Object b)
{
    Object t = b;
    b = a;
    a = t;
}

两者都将指向同一个对象,但更改第二个对象不会反映在此方法的更大范围内......

虽然我不完全明白这个问题......

于 2011-04-29T03:20:25.033 回答