昨天我正和一位同事谈论这件事,这让我想到了.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将如何为它生成程序集.感谢所有的答案,我从一个角度发现它们都是正确的,但我选择了一个最接近我认为我问过的问题的答案.
正确的思考方式ref是存储位置的别名.因此,当你说
int x;
Foo(ref x);
Run Code Online (Sandbox Code Playgroud)
并被Foo宣布为
void Foo(ref int y)
Run Code Online (Sandbox Code Playgroud)
您将在上面的方法调用中考虑x和y作为同一位置的别名.
因此,void Foo(ref int y)在C#中与void Foo(int &y)C++ 类似.
引用不是指针.
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,不同之处在于存储在通过引用传递存储器单元中的值不是一个对象,但实际值的参考.
在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的变量的引用.
明白了吗?
| 归档时间: |
|
| 查看次数: |
1550 次 |
| 最近记录: |