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)
所以是ref和out关键字,比如C#的指针,而无需使用unsafe代码?
Dan*_*ker 10
他们更有限.你可以说++上的指针,而不是一个ref或out.
编辑注释中的一些混淆,所以要绝对清楚:这里的重点是与指针的功能进行比较.您不能执行与/ ptr++上相同的操作,即使其处理内存中的相邻位置.这是真的(但在这里无关紧要),你可以执行相当于,但这将是它与值的能力,而不是指针.refout(*ptr)++
这是一个安全的赌注,他们只是内部指针,因为堆栈没有得到感动和C#是经过精心组织,以便ref和out总是指向堆栈的有源区.
编辑要绝对明确的再次(如果它不是已经从下面的例子清楚),这里的关键不在于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通过第一个字节可以访问所有字节; 它显然是指向第一个字节的指针.