c#ref int foo是否实现为c++;国际**foo?
昨天我和一位同事讨论了这件事,这让我想到了.Net的“通过引用传递”c#ref int foo是否实现为c++;国际**foo?,c#,.net,C#,.net,昨天我和一位同事讨论了这件事,这让我想到了.Net的“通过引用传递” // C# class Foo {} static void Test(ref Foo foo) { ... }; static void Main() { Foo f; Test(ref foo); } 必须使用双间接寻址来实现,因为我们正在更改指针的值。因为所有引用类型都是引用(指针) 等同于 // C++ void Test(Foo *foo); void Test(Foo **foo); 但是如
// C#
class Foo {}
static void Test(ref Foo foo) { ... };
static void Main()
{
Foo f;
Test(ref foo);
}
必须使用双间接寻址来实现,因为我们正在更改指针的值。因为所有引用类型都是引用(指针)
等同于
// C++
void Test(Foo *foo);
void Test(Foo **foo);
但是如果这是一个值类型,我们实际上不需要双间接寻址。所以我很好奇
// C#
static void Test(ref int bar) { ... }
变成
// C++
void Test(int *bar);
// or
void Test(int **bar);
2010年1月29日更新:
阅读所有的答案,我意识到我并不是完全清楚我想要什么,我误导了C++。我主要感兴趣的是它是如何在CLR中实现的,以及JIT将如何为它生成程序集。感谢所有的答案,我发现它们从某个角度来看都是正确的,但我选择了一个最接近我想问的问题。参考是&不是*你把它和指针混淆了。因此,这意味着它将作为:
void Test(Foo &bar);
我很确定像int这样的值类型只会使用单一级别的间接寻址。考虑
ref
的正确方法是存储位置的别名。因此,当你说
int x;
Foo(ref x);
并且Foo
被声明为
void Foo(ref int y)
您可以将x
和y
视为上述方法调用中相同位置的别名
< > >代码>空fo(REF INTY)<代码> >类似于C++中的代码>虚空FO(int和y)< /> > .< /p> 引用不是指针。< /p>
这声明了一个“内存单元”,其中包含对Foo实例的引用。然后它初始化
Foo
的一个新实例,并将引用存储在内存单元中
Bar(Foo x) { x = new Foo(); }
这使用Foo
参数声明方法,该参数本质上是一个局部变量(如Foo),当使用参数调用该方法时,会自动赋值
方法中的语句创建Foo
的新实例,并将对该实例的引用存储在内存单元x
中。存储单元foo
保持不变
Bar(foo);
通过将存储在存储单元foo
中的值复制到存储单元x
--按值调用,调用Bar
如果您写入int
而不是Foo
,则会发生完全相同的情况,只是存储在存储单元中的值不是参考值,而是实际值
这声明了一个带有
Foo&
参数的方法,该参数本质上是一个局部变量,它包含一个内存单元的地址,该内存单元包含对Foo
类型的对象的引用
Qux(ref x);
这将通过将y
设置为存储单元x
--的地址来调用Qux
Qux
中的语句创建Foo
的新实例,并将对对象的引用存储在位于地址y
(即Foo
的地址)的内存单元中。因此foo
被分配了对新实例和更改的引用
当Foo
是int
时,也会发生完全相同的情况,只是通过引用传递的存储单元中存储的值不是对对象的引用,而是实际值
MyClass
-->MyClass*
(或者,实际上,shared\u ptr
)ref
-->&
void M(ref int f) { }
你管它叫什么
int x = 123;
M(ref int x):
这是怎么回事
从逻辑上讲,这意味着“x和f指的是相同的存储位置”
我们在CLR中实际实现f的方式是“托管引用到可以包含整数的变量”。我们将局部变量x的托管地址传递给M
<> C++中的模拟是一种方法,它使用ANN& INT--对包含INT.< /P>的变量的引用。
清楚吗?您可能想检查它是如何在C++/CLI中实现的。我在一本书中找到了很好的解释:第83页
Foo^
被定义为“指向Foo的托管指针”,相当于UnmanagedFoo*
int%
和Foo^%
是“托管引用”,它们等同于int&
和UnmanagedFoo*&
,参见Jon Skeets关于参数传递的文章“但如果这是引用类型,我们实际上不需要双间接寻址。”-这可能是真的,也可能不是真的,取决于需要什么。有时引用类型的ref
参数很有用。@Michael:是的,当你想更新引用而不是对象本身时。你的意思是说“如果这是一个值类型,我们实际上不需要双重间接寻址”,对吗?很抱歉搞混了,Eric你完全正确,我指的是值而不是引用。一个非常不幸的错误。在ABI级别,这是相同的事情:通过BAR的地址。我理解这个观点作为适当的上下文来考虑抽象的CLR脱离实际的实现。也许当我问C++中发生了什么时,我误导了人们。我更感兴趣的是JIT将在组装中产生什么。即使在C++中,引用(在示例中的y)也用指针实现。我只是使用C++,因为我错误地认为它是足够的表达和低水平,许多人会熟悉它。
Qux(ref x);
void doSomething(int myInt);
void doSomethingElse(ref int myIntRef);
void doSomething(Foo foo);
void doSomethingElse(ref Foo fooRef);
void doSomething(int myInt);
void doSomethingElse(int& myInt);
void doSomething(Foo* fooPtr);
void doSomething(Foo*& fooPtrRef);
void M(ref int f) { }
int x = 123;
M(ref int x):