Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c#ref int foo是否实现为c++;国际**foo?_C#_.net - Fatal编程技术网

c#ref int foo是否实现为c++;国际**foo?

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); 但是如

昨天我和一位同事讨论了这件事,这让我想到了.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#
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
    -->
    &
  • C#:

    C++:

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

    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):