牧光小院

被约束的日日夜夜,停不下来的时间。

C++/CLI中的Handle和Reference小记

最近看了看C++/CLI specification。 的确,C++/CLI让C++在使用.NET的时候手感好了很多,一点学习小记,说的不对,各位多包涵。


Handle Type

对于CLI中的任意一个类型TT^声明了一个Thandle类型,它用来指向创建在CLI Heap上的对象。由于创建载托管堆上的对象的位置有可能被运行时改变,因此,一个Handle类型可以动态跟踪其指向的对象。从某种意义上说,我们可以把Handle类型看作是托管堆上的指针,而把native pointer看作是原生堆上的指针。

一个handle类型变量的默认值是nullptr

通过gcnew关键字,你可以在托管堆上创建一个CLI对象,这样的对象只能够通过handle来访问。例如:

R^ r1 = gcnew R; // Allocate an Object on the CLI heap

R^ r2 = r1;   // Handles r1 and r2 refer to the same object

除非使用delete或者显式调用一个CLI对象的析构函数,否则CLI对象的析构函数绝对不会被调用。但是,当程序结束的时候,GC会回收对象的内存,并且如果一个对象有finalizer,这个东西倒是会被调用。例如:

ref class T {

public :

    T() { }

    ~T() {

        System::Console::WriteLine("I'm destructor!"); }

    !T() {

        System::Console::WriteLine("I'm finalizer!");

    }

};

之后:

{

        T^ t1 = gcnew T();

}

会看到只有finalizer被调用了,而:

{

        delete t;

}

会看到析构函数被调用了。也就是说,对于一个托管对象,有2种清理方式。一种是通过析构函数进行确定性的清除;另一种是让CLI调用类对象的finalizer

l          和原生指针不同,handle类型的变量具有跟踪功能,也就是说一个handle类型的变量可以根据其指向的CLI heap中对象的位置而改变(因为GC可能会移动托管堆中的对象)。也就是说:handle类型不能转换成void*,也不能进行相反的转换

l          handle 类型不能转换成整数类型,也不能进行相反的转换

l          不能对handle类型进行排序

l          Handle 类型的变量只能指向CLI heap中的对象

例如:

R^ r4 = new R; 

Object^ o = r4;// OK

R^ r5 = dynamic_cast(o); // OK r4 and r5 point to the same object

long l = reinterpret_cast<long>(r5); //error, can't convert to integer

R^ r6 = reinterpret_cast(l);    // error, can't convert from integer

std::set s; // error, R^ can't be compared with less

所有指向同一个托管对象的引用都可以被看作是等价的,即使对象被GC移动了也是如此。一个handle可以有任意的生存周期。也可以被指定成nullptr。对于一个handle类型的变量,你也可以通过*来或得其指向的对象的引用。

Reference Type

一个原生引用可以被邦定到任何做为左值的原生变量(lvalue)上。

作为一个托管堆中的对象,由于GC有可能移动它的位置,因此它的位置必须被跟踪。因此,对于这样的对象的引用被称为tracking reference%),由于存在gc-lvaluelvalue的隐式转换,所以一个track reference可以既可以邦定到gc-lvalue,也可以邦定到lvalue。当其邦定到一个lvalue时,取其地址获得的是一个原生指针,否则获得的就是一个托管handle。例如:

R^ h = gcnew R; // allocate on CLI heap

R& r = *h;      // bind tracking reference to ref class obj

void F(V% r);

F(*gcnew V);  // bind tracking reference to value class obj

N* p = new N();

N% rn = *p;    // bind to native object;

和一个普通的引用一样,一个tracking reference也是不可以重邦定的。一旦在声明时被指定了对象,就不可以再进行更改。另外你也只可以把tracking reference类型的变量定义成automatic型的。

如果一个tracking reference被邦定到某个值类型的基类,那么这个tracking reference便不能邦定到这个派生的值类型。也就是说一个System::Object%不可以邦定到一个System::ValueType对象上。

 

posted on 2005-11-03 11:18 nacci 阅读(2750) 评论(1)  编辑 收藏 引用

评论

# re: C++/CLI中的Handle和Reference小记 2008-02-18 10:46 dee

建议看看这篇文章对你会有帮助的 http://www.150it.cn/bianchengwendang/VC/865064948.html  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2008年2月>
272829303112
3456789
10111213141516
17181920212223
2425262728291
2345678

导航

统计

常用链接

留言簿(2)

随笔分类

收藏夹

大家的声音

积分与排名

最新评论

阅读排行榜

评论排行榜