c#ref int foo是作为C++ int**foo实现的吗?

Pet*_*ert 3 .net c#

昨天我正和一位同事谈论这件事,这让我想到了.Net的传递参考.

// C#
class Foo {}

static void Test(ref Foo foo) { ... };
static void Main()
{ 
    Foo f;
    Test(ref foo);
}
Run Code Online (Sandbox Code Playgroud)

必须使用双重间接实现,因为我们正在更改指针的值.因为所有引用类型都是引用(指针)

// C#
static void Test(Foo foo) { ... }
static void Test(ref Foo foo) { ... };
Run Code Online (Sandbox Code Playgroud)

相当于像

// C++
void Test(Foo *foo);
void Test(Foo **foo);
Run Code Online (Sandbox Code Playgroud)

但如果这是一个VALUE类型,我们实际上并不需要双重间接.所以我很好奇

// C#
static void Test(ref int bar) { ... }
Run Code Online (Sandbox Code Playgroud)

// C++
void Test(int *bar);
// or
void Test(int **bar);
Run Code Online (Sandbox Code Playgroud)

1/29/10更新:阅读所有答案后,我意识到我对自己想要的内容并不十分清楚,而且我误导了将C++投入到正在发生的事情中.我最感兴趣的是它是如何在CLR中实现的,以及JIT将如何为它生成程序集.感谢所有的答案,我从一个角度发现它们都是正确的,但我选择了一个最接近我认为我问过的问题的答案.

jas*_*son 6

正确的思考方式ref是存储位置的别名.因此,当你说

int x;
Foo(ref x);
Run Code Online (Sandbox Code Playgroud)

并被Foo宣布为

void Foo(ref int y)
Run Code Online (Sandbox Code Playgroud)

您将在上面的方法调用中考虑xy作为同一位置的别名.

因此,void Foo(ref int y)在C#中与void Foo(int &y)C++ 类似.


dtb*_*dtb 5

引用不是指针.


Foo foo = new Foo();
Run Code Online (Sandbox Code Playgroud)

这声明了一个"内存单元",它包含对Foo实例的引用.然后它初始化一个新实例Foo并将引用存储在存储单元中.

Bar(Foo x) { x = new Foo(); }
Run Code Online (Sandbox Code Playgroud)

这声明了带有Foo参数的方法,该参数本质上是一个局部变量(如foo),当使用参数调用方法时,该变量恰好被自动分配.

方法中的语句创建一个新实例,Foo并将该实例的引用存储在内存单元中x.记忆细胞foo保持不变.

Bar(foo);
Run Code Online (Sandbox Code Playgroud)

Bar通过将存储在存储器单元中的值复制到存储器单元foo调用x - 按值调用.

除非存储在存储单元中的值不是参考而是实际值,否则如果您编写int而不是Foo,则完全相同.


Qux(ref Foo y) { y = new Foo(); }
Run Code Online (Sandbox Code Playgroud)

这声明了一个带有Foo&参数的方法,该参数本质上是一个局部变量,它包含一个存储单元的地址,该存储单元保存对类型对象的引用Foo.

Qux(ref x);
Run Code Online (Sandbox Code Playgroud)

Qux通过设置y为存储单元的地址来调用x - 通过引用调用.

该语句Qux创建一个新实例,Foo并将对象的引用存储在位于地址y(即地址 foo)的存储单元中.因此foo分配了对新实例和更改的引用.

完全相同的情况发生时Foo是一个int,不同之处在于存储在通过引用传递存储器单元中的值不是一个对象,但实际值的参考.


Eri*_*ert 5

在C#中,当你有一个方法

void M(ref int f) { }
Run Code Online (Sandbox Code Playgroud)

你打电话给它

int x = 123;
M(ref int x):
Run Code Online (Sandbox Code Playgroud)

这是如何运作的?

从逻辑上讲,这意味着"x和f指的是相同的存储位置".

我们在CLR中实际实现的方式是f类型为"可以包含整数的变量的托管引用".我们将局部变量x的托管地址传递给M.

C++中的类比将是一个带有&int的方法 - 对可以包含int的变量的引用.

明白了吗?