在C#中的引用和输出是否与C ++中的指针相同? [英] Are ref and out in C# the same a pointers in C++?

查看:140
本文介绍了在C#中的引用和输出是否与C ++中的指针相同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚在C#中做了一个Swap例程,如下:

  static void Swap(ref int x,ref int y) 
{
int temp = x;
x = y;
y = temp;
}

它与C ++代码所做的事情相同:

  void swap(int * d1,int * d2)
{
int temp = * d1;
* d1 = * d2;
* d2 = temp;
}

ref out 代码?

解决方案

他们更有限。你可以对指针说++,但不能在 ref out 上。






EDIT 在注释中有些混乱,所以要绝对清楚:这里的要点是与指针的功能。您不能对 ref / out ptr ++ 相同的操作c $ c>,即使其寻址存储器中的相邻位置。这是真的(但在这里不相关),你可以执行等效的(* ptr)++ ,但这将是与 values ,而不是指针。






这是一个安全的赌注,他们在内部只是指针,移动和C#是仔细组织,使 ref out 总是指的堆栈的活动区域。 p>




EDIT 要再次完全清除(如果下面的例子还不清楚) ,这里的要点不是 c 指向堆栈, c 这是 当它指向堆栈,它是由语言规则保证不成为悬空指针。这种保证是必要的(在这里是相关的/有趣的),因为堆栈只是按照方法调用退出丢弃信息,没有检查,以确保任何引用仍然存在。



相反,当 ref / out 引用GC堆中的对象时,不必担心这些对象能够保持活动只要有必要:GC堆被精确设计为保留对象的任何时间所需的时间,它们的引用,并提供钉住(见下面的例子),以支持对象不能通过GC压缩移动的情况。 / p>




如果你曾经在不安全代码中使用interop,你会发现 ref 与指针非常密切相关。例如,如果COM接口声明如下:

  HRESULT写(BYTE * pBuffer,UINT size); 

互操作程序集会将其转换为:

  void Write(ref byte pBuffer,uint size); 

您可以这样做来调用它(我相信COM互操作的东西照顾着数组):

  byte [] b = new byte [1000] 
obj.Write(ref b [0],b.Length);

换句话说, ref 字节让你访问它的所有;它显然是一个指向第一个字节的指针。


I just made a Swap routine in C# like this:

static void Swap(ref int x, ref int y)
{
    int temp = x;
    x = y;
    y = temp;
}

It does the same thing that this C++ code does:

void swap(int *d1, int *d2)
{
    int temp=*d1;
    *d1=*d2;
    *d2=temp;
}

So are the ref and out keywords like pointers for C# without using unsafe code?

解决方案

They're more limited. You can say ++ on a pointer, but not on a ref or out.


EDIT Some confusion in the comments, so to be absolutely clear: the point here is to compare with the capabilities of pointers. You can't perform the same operation as ptr++ on a ref/out, i.e. make it address an adjacent location in memory. It's true (but irrelevant here) that you can perform the equivalent of (*ptr)++, but that would be to compare it with the capabilities of values, not pointers.


It's a safe bet that they are internally just pointers, because the stack doesn't get moved and C# is carefully organised so that ref and out always refer to an active region of the stack.


EDIT To be absolutely clear again (if it wasn't already clear from the example below), the point here is not that ref/out can only point to the stack. It's that when it points to the stack, it is guaranteed by the language rules not to become a dangling pointer. This guarantee is necessary (and relevant/interesting here) because the stack just discards information in accordance with method call exits, with no checks to ensure that any referrers still exist.

Conversely when ref/out refers to objects in the GC heap it's no surprise that those objects are able to be kept alive as long as necessary: the GC heap is designed precisely for the purpose of retaining objects for any length of time required by their referrers, and provides pinning (see example below) to support situations where the object must not be moved by GC compacting.


If you ever play with interop in unsafe code, you will find that ref is very closely related to pointers. For example, if a COM interface is declared like this:

HRESULT Write(BYTE *pBuffer, UINT size);

The interop assembly will turn it into this:

void Write(ref byte pBuffer, uint size);

And you can do this to call it (I believe the COM interop stuff takes care of pinning the array):

byte[] b = new byte[1000];
obj.Write(ref b[0], b.Length);

In other words, ref to the first byte gets you access to all of it; it's apparently a pointer to the first byte.

这篇关于在C#中的引用和输出是否与C ++中的指针相同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆