科技时代新浪首页 > 科技时代 > 学园 > 正文

C++/CLI解析之基于堆栈的对象与跟踪引用


http://www.sina.com.cn 2006年10月18日 09:15 天极yesky

  作者:谢启东编译

  在托管堆上分配对象实例,似乎是使用托管扩展C++、C#、J#、VB.NET程序员的唯一方法,而使用本地C++的程序员,不但可以在堆上分配内存,甚至更惯于使用基于堆栈的对象实例。

  现在回顾一下以前定义的Point引用类,再来看一下以下变量定义:

Point p1, p2(3,4);

  从本地C++的角度来说,p1与p2应为基于堆栈的引用类Point实例,哪怕是从一般性的角度来看,它们也是。P1由默认的构造函数初始化,而p2由接受x与y坐标的构造函数初始化。从实现上来看,Point是自包含类型的(也就是说,它不包含任何指针或句柄),然而,作为一个引用类的实例,它仍处于CLI运行时的掌控之下,且在必要时,会被垃圾回收--正因为此,所以不能定义一个引用类的静态或全局实例。

  同时,也不能将sizeof应用于指明是引用类实例的表达式,因为sizeof是在编译时进行计算的,而Point对象的大小要直到运行时才能确定;但是,可将sizeof应用于句柄,因为它的大小在编译时就已经确定了。

  另外,还不能定义一个基于堆栈的CLI数组实例。

  跟踪引用

  本地C++可通过&来定义一个对象的别名,例如,对任意本地类N,可编写如下代码:

N n1;
N& n2 = n1;

  引用必须在定义时进行初始化,且在整个生命期中,它们都锁定于引用同一对象,也就是说,它的值不会改变。引用一个引用类的实例与引用一个本地类基本一致,只不过语法不同而已。

  在程序执行期间,引用类的实例会在内存中"移动",所以,需要对它们进行跟踪,而本地指针与引用却不能够胜任这项工作(尤其指不能对一个引用类的实例使用取地址符&),因此,C++/CLI对应地提供了句柄及用于跟踪的引用--在此简称为跟踪引用(Tracking References),例如,你可以定义一个跟踪引用p3,以追踪对象p2:

Point% p3 = p2;

  跟踪引用的内存存储方式必须为自动(atuomatic),另外,尽管本地对象不会在内存中"移动",但在上面的n2中,不能使用%来代替&。在C++/CLI中,%之于^,就如同本地C++中的&之于*。

  请看下列代码:

Point^ hp = gcnew Point(2,5);
Point% p4 = *hp;
Point% p5 = *gcnew Point(2,5);

  在此,hp是一个Point的句柄,而p4是此句柄的别名。虽然句柄不是一个指针,但也能使用一元 * 操作符来对句柄解引用。(在C++/CLI标准制定期间,是否就引入一元 ^ 操作符来取代 * 还进行过一场讨论,反方观点是,在编写模板时,* 对句柄或指针进行解引用有非常高的价值。)当然,即使hp有了一个新值,p4在此仍是同一Point的别名。另外要说明一点,当对象有一个句柄或跟踪引用时,就不能被垃圾回收器回收了。

  再来看p5,对gcnew返回的句柄进行了解引用,虽然差不多每个引用类类型的句柄,都能被解引用,但有两种类型的句柄却不能被解引用,这两种类型是:System::String与array<T>。

 [1] [2] [3] [4] [下一页]

本文导航:
·C++/CLI解析之基于堆栈的对象与跟踪引用
·C++/CLI解析之基于堆栈的对象与跟踪引用(2)
·C++/CLI解析之基于堆栈的对象与跟踪引用(3)
·C++/CLI解析之基于堆栈的对象与跟踪引用(4)

发表评论 _COUNT_条

爱问(iAsk.com)



评论】【论坛】【收藏此页】【 】【多种方式看新闻】【下载点点通】【打印】【关闭




科技时代意见反馈留言板 电话:010-82628888-5595   欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

Copyright © 1996 - 2006 SINA Inc. All Rights Reserved

新浪公司 版权所有