对象引用与托管指针(object references and managed pointers)

C/C++中的指针是一种非常灵活而强大的引用机制,但同时也非常脆弱,稍有不慎,就会出错。
 
Java完全摈弃了指针的概念,而代之以对象引用(object reference),基本上消灭了由指针而导致的错误。
 
C#借鉴了Java的作法,引入了对象引用的概念,但同时,不像Java做的那么绝,仍然提供了指针的概念。
 
CLR支持三种类型的指针:
 
1) 托管指针(managed pointers)
2) 非托管指针(unmanaged pointers)
3) 非托管函数指针(unmanaged function pointers)
 
托管指针是一种新类型的指针,指向托管堆中的内存区。
非托管指针是传统的C/C++指针,指向非托管内存区。
非托管函数指针也是传统的C/C++指针,指向函数地址。
 
C#中的指针属于非托管指针,在C#中不能直接使用托管指针,但作为 by-ref 参数传递机制的 ref 和 out 机制就是利用托管指针实现的。
 
C#代码:
 
using System;
public class Test
{
public static void Main()
{
int n = 20;
int m;
 
compute(n, out m);
}
private static void compute(int x, out int y)
{
y = x * 2;
}
}
 
编译以后,生成如下 IL 代码(为了简单起见,这里只取compute()方法的 IL 代码):
 
.method private hidebysig static void  compute(int32 x, [out] int32& y) cil managed
{
  // Code size       7 (0x7)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldarg.1
  IL_0002:  ldarg.0
  IL_0003:  ldc.i4.2
  IL_0004:  mul
  IL_0005:  stind.i4
  IL_0006:  ret
} // end of method Test::compute
 
从compute()的 IL 代码即可明显看出,参数 y 的类型即是托管指针 int32&。
 
stind.i4 指令将栈顶的 32 位整数值存储到由次栈顶元素(即参数 y)所指示的内存地址中。
 
上面的C#代码用的是 out 指示符,如果换成 ref 指示符,生成的 IL 代码是一样的,所不同的是,C#编译器会检查 m 的赋值情况,在执行 compute(n, ref m) 之前,m 必须被明确赋值(definite assigned),而对于 out 指示符,m 不需要赋值。
 
托管指针和非托管指针的区别是明显的,托管指针指向的是托管堆中的地址,而非托管指针指向的是非托管内存中的地址。
 
那么,对象引用与托管指针又有什么不同呢?
 
从物理实现的角度看,对象引用也是一种指针,而且是一种托管类型的指针。与托管指针不同,对象引用只能指向对象的起始位置,而不能指向对象内部,也就是说,对象引用指向的是对象的整体,而非局部。
 
而托管指针一般是指向对象内部某个成员的地址。除此之外,托管指针还可以指向求值栈(evaluation stack)中的位置,或静态变量,甚至非托管内存区。
 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/9537936/viewspace-406714/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/9537936/viewspace-406714/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值