设为首页 加入收藏

TOP

4.6.1 跟踪句柄
2013-10-07 12:27:29 来源: 作者: 【 】 浏览:66
Tags:4.6.1 跟踪

4.6.1  跟踪句柄

跟踪句柄类似于本地C++(www.cppentry.com)指针,但也有明显不同的地方。跟踪句柄确实存储着某个地址,如果堆压缩过程中移动了句柄引用的对象,垃圾回收器将自动更新句柄包含的地址。但是,我们不能像使用本地指针那样使用跟踪句柄执行地址的算术操作,跟踪句柄的强制类型转换也是不允许的。

在CLR堆中创建的所有对象都必须被跟踪句柄引用。所有属于引用类类型的对象都存储在堆中,因此为引用这些对象而创建的变量都必须是跟踪句柄。例如,String类属于引用类类型,因此引用String对象的变量必须是跟踪句柄。供数值类类型使用的内存默认是在堆栈上分配的,但我们也可以通过使用gcnew运算符选择将数值存储在堆上。此刻又是一个很好的机会来回忆一下第2章曾经提到的一点:在CLR堆上分配的变量-- 其中包括所有CLR引用类型,都不能在全局作用域中声明。

声明跟踪句柄

我们通过将符号^(通常被称为"帽子")放在类型名称的后面来指定该类型的句柄。例如,下面这条语句就声明了一个可以存储String类型对象的地址、名为proverb的跟踪句柄:

  1. String^ proverb; 

该语句定义的proverb变量是String^类型的跟踪句柄。当我们声明某个句柄时,系统自动将其初始化为空值,因此该句柄将不引用任何对象。为显式地将某个句柄设置为空值,我们可以像下面这样使用关键字nullptr:

  1. proverb = nullptr;  // Set handle to null 

注意,我们在这里不能像使用本地指针时那样,使用0来表示空值。如果用0来初始化句柄,则数值0将被转换为该句柄引用的对象的类型,而这个新对象的地址将被存入该句柄中。

当然,我们可以在声明时显式地初始化句柄。下面这条语句定义的也是指向String对象的句柄:

  1. String^ saying = L"I used to think I was 
    indecisive but now I'm not so sure"

该语句在堆上创建一个包含等号右边字符串的String对象,该新建对象的地址被存入saying中。注意,字符串字面值的类型是const wchar_t*,而非String。定义String类的方式使这样的字面值可以用来创建String类型的对象。

下面这条语句给出为数值类型创建句柄的方法:

  1. int^ value = 99

该语句创建一个int^类型的句柄value,并将堆内该句柄指向的数值初始化为99。记住,我们创建的是一种指针,因此在没有解除引用的情况下value不能参与算术运算。为了解除对跟踪句柄的引用,我们以与使用本地指针时相同的方式使用*运算符。例如,下面这条语句就在算术运算中使用了跟踪句柄指向的值:

  1. int result = 2*(*value)+15; 

圆括弧内的表达式*value访问该跟踪句柄指向的地址存储的整数,因此变量result的结果是213。

注意,当我们在等号左边使用句柄时,不需要显式解除引用就可以用来存储结果,编译器将替我们处理好一切。例如:

  1. int^ result = 0;  
  2. result = 2*(*value)+15; 

在此首先创建一个指向数值0的句柄result。注意,第一行将使编译器产生一条警告消息,因为编译器认为我们可能打算将句柄初始化为空值,但这种写法是错误的。因为在下一条语句中result出现在等号左边,而右边的结果是数值,所以编译器能够判定必须解除对result的引用才能存储数值。当然,我们也可以将这条语句写成下面的显式形式:

  1. *result = 2*(*value)+15; 

注意,仅当真正定义过result之后,这条语句才能工作。如果只是声明了result,则执行上述代码时将产生运行时错误。例如:

  1. int^ result;            // Declaration but no definition  
  2. *result = 2*(*value)+15;        // Error message - unhandled exception 

第二条语句要解除对result的引用,这意味着被指向的对象已经存在。但实际上并不然,所以程序将产生运行时错误。第一条语句是句柄result的声明,该句柄默认情况下被设置为空值,而我们不能解除对空句柄的引用。如果我们不在第二条语句中显式解除对result的引用,则一切都将像预期的那样正常工作。因为等号右边表达式的结果是数值类类型,所以其地址被存入result中。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇4.6.2 CLR数组(1) 下一篇0.2 本书主要内容

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: