C++:最强大的.NET语言之内存与资源(二)

2014-11-24 13:19:59 · 作者: · 浏览: 33
alize方法,编译器实际上插入了一个try-finally块并调用基类的Finalize方法,因此,C#与托管C++相对容易编写一个Finalize方法,但在编写Dispose方法时,却没有提供任何帮助。程序员们经常使用Dispose方法,把它当作一个伪析构函数以便在代码块末执行一点其他的代码,而不是为了释放任何资源。

  C++/CLI认识到了Dispose方法的重要性,并在引用类型中,使之成为一个逻辑"析构函数"。

ref class Derived : Base
{
 ~Derived() //实现或重载IDisposable::Dispose方法
 {
  //释放托管与非托管资源
 }

 !Derived() //实现或重载IDisposable::Dispose方法
 {
  //只释放非托管资源
 }
};

  对C++程序员来说,这让人感觉更自然了,能像以往那样,在析构函数中释放资源了。编译器会生成必要的IL(中间语言)来正确实现IDisposable::Dispose方法,包括抑制垃圾回收器调用对象的任何Finalize方法。事实上,在C++/CLI中,显式地实现Dispose方法是不合法的,而从IDisposable继承只会导致一个编译错误。当然,一旦类型通过编译,所有使用该类型的CLI语言,将只会看到Dispose模式以其每种语言最自然的方式得以实现。在C#中,可以直接调用Dispose方法,或使用一个using语句--如果类型定义在C#中。那么C++呢?难道要对堆中的对象正常地调用析构函数?此处当然是使用delete操作符了,对一个句柄使用delete操作符将会调用此对象的Dispose方法,而回收对象的内存是垃圾回收器该做的事,我们不需要关心释放那部分内存,只要释放对象的资源就行了。

Derived^ d = gcnew Derived();
d->SomeMethod()
delete d;

  如果表达式中传递给delete操作符的是一个句柄,将会调用对象的Dispose方法,如果此时再没有其他对象链接到引用类型,垃圾回收器就会释放对象所占用的内存。如果表达式中是一个本地C++对象,在释放内存之前,还会调用对象的析构函数。

  毫无疑问,在对象生命期管理上,我们越来越接近自然的C++语法,但要时刻记住使用delete操作符,却不是件易事。C++/CLI允许对引用类型使用堆栈语义,这意味着你能用在堆栈上分配对象的语法来使用一个引用类型,编译器会提供给你所期望的C++语义,而在底层,实际上仍是在托管堆中分配对象,以满足CLR的需要。

Derived d;
d.SomeMethod();

  当d超出范