C#中的ref和out是否与C++中的指针相同?

Bob*_*lan 8 c# c++ pointers unsafe ref

我只是用C#做了一个Swap例程:

static void Swap(ref int x, ref int y)
{
    int temp = x;
    x = y;
    y = temp;
}
Run Code Online (Sandbox Code Playgroud)

它与C++代码的作用相同:

void swap(int *d1, int *d2)
{
    int temp=*d1;
    *d1=*d2;
    *d2=temp;
}
Run Code Online (Sandbox Code Playgroud)

所以是refout关键字,比如C#的指针,而无需使用unsafe代码?

Dan*_*ker 10

他们更有限.你可以说++上的指针,而不是一个refout.


编辑注释中的一些混淆,所以要绝对清楚:这里的重点是与指针的功能进行比较.您不能执行与/ ptr++上相同的操作,即使其处理内存中的相邻位置.这是真的(但在这里无关紧要),你可以执行相当于,但这将是它与的能力,而不是指针.refout(*ptr)++


这是一个安全的赌注,他们只是内部指针,因为堆栈没有得到感动和C#是经过精心组织,以便refout总是指向堆栈的有源区.


编辑要绝对明确的再次(如果它不是已经从下面的例子清楚),这里的关键不在于ref/ out指向堆栈.那就是它指向的堆栈,它是由语言规则保证不会成为一个悬摆指针.这种保证是必要的(并且相关/有趣),因为堆栈只是根据方法调用退出丢弃信息,没有检查以确保任何引用仍然存在.

相反,当ref/ out表示GC堆中的对象时,这些对象只要有必要就能保持活动就不足为奇了:GC堆的设计恰好是为了保留引用者所需的任何时间长度的对象,并且提供固定(参见下面的示例)以支持不能通过GC压缩移动对象的情况.


如果您在不安全的代码中使用互操作,您会发现它ref与指针密切相关.例如,如果COM接口声明如下:

HRESULT Write(BYTE *pBuffer, UINT size);
Run Code Online (Sandbox Code Playgroud)

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

void Write(ref byte pBuffer, uint size);
Run Code Online (Sandbox Code Playgroud)

你可以这样做来调用它(我相信COM互操作的东西负责固定数组):

byte[] b = new byte[1000];
obj.Write(ref b[0], b.Length);
Run Code Online (Sandbox Code Playgroud)

换句话说,ref通过第一个字节可以访问所有字节; 它显然是指向第一个字节的指针.


jal*_*alf 6

C#中的引用参数可用于替换指针的一种用法,是的.但不是所有的.

指针的另一个常见用途是作为迭代数组的手段.out/ref参数不能这样做,所以不,它们不是"与指针相同".