[C++/CLI] 析构函数等于IDisposable::Dispose()方法
2004-10-14 21:45
423 查看
在以前的一篇帖子里我曾提到在C++/CLI中,会自动调用Dispose()方法。但那个时候只是从msdn上的文章中知道这样一个特性,还没有编译器的支持,所以一切也只能是纸上谈兵,很多细节都很不明朗。VC会以什么样的方式来提供这一特性,一直是我常思考的问题。然而甚至到VS.net 2005 beta1发布时,这一特性还没有得到支持。
好在,在最新的Visual C++ 2005 Tool Refresh中的编译器,已经支持了这一特性。那么就让我们来一探究竟吧。
首先,在最新的编译器中,如果一个类定义了析构函数,编译器会自动让类实现IDisposable接口,并把析构函数映射到Dispose()方法上。假如我们定义以下这个类
它最终生成的IL代码是这样的。
我们可以看到它已经实现了IDisposable接口,并且Dispose方法的内容就是析构函数的内容。
其次为了能够确定自动调用Dispose()方法的时机,C++/CLI现在支持一种新的对象实例化语法。
通常为了获得一个类的实例,我们需要这样写:
Test^ t = gcnew Test();
但为了获得自动调用Dispose()方法的好处,我们必须以这样的语法来实例化类:
Test t;
这就仿佛native c++中在栈(Stack)上实例化了一个对象一样。当然这只是一个语法的模仿,真正的对象还是在堆中实例化的。然而以这种方法实例化,就告诉了编译器,但退出对象申明所在的作用域时,希望能自动调用对象的Dispose()方法。
让我们来看一个函数:
观察函数的IL代码,可以发现调用Dispose()方法的代码已经被加入到方法中了。并且为了在抛出异常时,也能调用Dispose()方法,编译器还自动加上了一个try块。
以上的foo()函数,如果用C#来写,会是这样:
void foo()
{
using (Test t = new Test())
{
}
}
然而,大家都知道using有一个最大的缺点,就是一次只能实例化一个对象。而在ado.net的程序中,经常我们会需要一次申明几个对象。这时候using语句就无能为力了。而C++/CLI提供的这一机制,完美地解决了这一问题。你可以一次申明多个对象,当这些对象退出作用域时,就会自动Dispose。
并且,作用域的识别方法和native c++中是一致的。也就是说你可以添加一对大括号来构成一个作用域,而不一定要是一个函数,就像这样:
值得注意的是,虽然在这个post中,我用了“对象退出作用域”这样的词,但是这只是为了判断Dispose方法调用的时机,并不表明对象在退出作用域之后就被回收了,对象内存的回收仍然是GC操控的,就像C#的using语句中那样。
总得来说,C++/CLI在吸收了C#中using语句的经验与教训之后,为显式释放资源提供了一个完美的解决方案。
好在,在最新的Visual C++ 2005 Tool Refresh中的编译器,已经支持了这一特性。那么就让我们来一探究竟吧。
首先,在最新的编译器中,如果一个类定义了析构函数,编译器会自动让类实现IDisposable接口,并把析构函数映射到Dispose()方法上。假如我们定义以下这个类
它最终生成的IL代码是这样的。
我们可以看到它已经实现了IDisposable接口,并且Dispose方法的内容就是析构函数的内容。
其次为了能够确定自动调用Dispose()方法的时机,C++/CLI现在支持一种新的对象实例化语法。
通常为了获得一个类的实例,我们需要这样写:
Test^ t = gcnew Test();
但为了获得自动调用Dispose()方法的好处,我们必须以这样的语法来实例化类:
Test t;
这就仿佛native c++中在栈(Stack)上实例化了一个对象一样。当然这只是一个语法的模仿,真正的对象还是在堆中实例化的。然而以这种方法实例化,就告诉了编译器,但退出对象申明所在的作用域时,希望能自动调用对象的Dispose()方法。
让我们来看一个函数:
观察函数的IL代码,可以发现调用Dispose()方法的代码已经被加入到方法中了。并且为了在抛出异常时,也能调用Dispose()方法,编译器还自动加上了一个try块。
以上的foo()函数,如果用C#来写,会是这样:
void foo()
{
using (Test t = new Test())
{
}
}
然而,大家都知道using有一个最大的缺点,就是一次只能实例化一个对象。而在ado.net的程序中,经常我们会需要一次申明几个对象。这时候using语句就无能为力了。而C++/CLI提供的这一机制,完美地解决了这一问题。你可以一次申明多个对象,当这些对象退出作用域时,就会自动Dispose。
并且,作用域的识别方法和native c++中是一致的。也就是说你可以添加一对大括号来构成一个作用域,而不一定要是一个函数,就像这样:
值得注意的是,虽然在这个post中,我用了“对象退出作用域”这样的词,但是这只是为了判断Dispose方法调用的时机,并不表明对象在退出作用域之后就被回收了,对象内存的回收仍然是GC操控的,就像C#的using语句中那样。
总得来说,C++/CLI在吸收了C#中using语句的经验与教训之后,为显式释放资源提供了一个完美的解决方案。
相关文章推荐
- 自定义能够for each的类,C#,Java,C++,C++/cli的实现方法
- VS2010使用C++/CLI编程窗口无法显示问题解决方法
- ACE与C++/CLI集成使用时遇到的问题及解决方法
- C++使用构造和析构函数管理同步锁的一种方法Guard
- C++学习笔记4--静态属性 静态方法 虚方法 抽象方法 多态性 析构函数 运算符重载 多继承 虚继承
- 析构函数和Dispose方法的区别
- 走进C++程序世界-------类的定义和使用(数据成员和方法成员,析构函数,构造函数,内联实现)
- C++中构造函数和析构函数显式调用的方法
- 在C++/CLI的本地类中包含托管类成员变量的方法
- java的finalize( )方法与C++的析构函数
- C#中析构函数、Dispose、Close方法的区别
- 从Managed C++升级到C++/CLI时出现LNK2001错误的解决方法
- 强制回收和IDisposable.Dispose方法
- C++中构造函数和析构函数显式调用的方法
- 在C++/CLI的本地类中包含托管类成员变量的方法
- C++对象数组调用构造/析构函数的方法
- C++实现调用C#(CLI)方法
- java的finalize()方法与C++的析构函数
- 走进C++程序世界-------类的定义和使用(数据成员和方法成员,析构函数,构造函数,内联实现)
- OSG学习:C#调用非托管C++方法——C++/CLI