以文本方式查看主题

-  中文XML论坛 - 专业的XML技术讨论区  (http://bbs.xml.org.cn/index.asp)
--  『 Dot NET,C#,ASP,VB 』  (http://bbs.xml.org.cn/list.asp?boardid=43)
----  修订版Managed C++中析构函数的语义更改  (http://bbs.xml.org.cn/dispbbs.asp?boardid=43&rootid=&id=11802)


--  作者:admin
--  发布时间:11/9/2004 2:26:00 AM

--  修订版Managed C++中析构函数的语义更改


发信人: flier (小海 [寻找风车中]), 信区: DotNET
标  题: 修订版Managed C++中析构函数的语义更改
发信站: BBS 水木清华站 (Mon Mar 29 23:38:55 2004), 转信

http://61.155.107.20/user8/flier_lu/main.asp?id=1485755

修订版Managed C++中析构函数的语义更改

    上周Lippman在其Blog上发表了一篇介绍新版本Managed C++中析构函数语义变化的文章:Changes in Destructor Semantics in Support of Deterministic Finalization。
    我们知道在C#和Managed C++中,析构函数实际上被编译器翻译成对Object.Finalize函数的重载。例如在Managed C++中定义如下的类

以下为引用:

__gc class A
{
public:
  ~A() { Console::WriteLine(S"in ~A"); }
};

__gc class B : public A
{
public:
  ~B() { Console::WriteLine(S"in ~B");  }
};
  



    在Managed C++的实现上被编译器自动转换成

以下为引用:

// internal transformation of destructor under V1
__gc class A
{
public:
   void Finalize() { Console::WriteLine(S"in ~A"); }
};

__gc class B : public A
{
public:
  void Finalize()
  {
    Console::WriteLine(S"in ~B");

    A::Finalize();
  }
};
  



    但为了语义上兼容C++的程序,Managed C++同时也提供了一个虚方法实现析构函数。

以下为引用:

__gc class A
{
public:
  virtual ~A()
  {
    System::GC::SuppressFinalize(this);

    A::Finalize();
  }
};

__gc class B : public A
{
public:
  virtual ~B()
  {
    System::GC:SuppressFinalize(this);

    B::Finalize();
  }
};
  



    这样一来就允许Managed C++用户显式地调用类的Finalize()函数。
    虽然这样的思路在目前CLR版本中可以正常运转,但实际上和Dispose模式存在重合和冲突的地方,而且频繁使用Finalizer也会导致效率的降低。因此在新版本的Managed C++中,析构函数改为使用Dispose模式来实现。上面的代码被编译器自动转换为

以下为引用:

// internal transformation of destructor under V2
__gc class A : IDisposable
{
public:
  void Dispose()
  {
    System::GC::SuppressFinalize(this);

    Console::WriteLine( "in ~A"); }
  }
};

__gc class B : public A
{
public:
  void Dispose()
  {
    System::GC::SuppressFinalize(this);

    Console::WriteLine( "in ~B");

    A::Dispose();
  }
};
  



    而对此类进行的析构操作,无论是直接调用类的析构函数,还是通过delete关键字隐式调用,都会被编译器翻译成对Dispose方法的调用。
    但这样一来GC就无法访问类的析构代码了,因为析构函数没有直接被转换成Finalize函数。为此Managed C++新版本提供了一个修订语法,通过'!'前缀支持显式定义Finalize函数,例如:

以下为引用:

public ref class R
{
public:
  !R() {  Console::WriteLine( "I am the R::finalizer()!" ); }
};
  



    被新版本Managed C++编译器自动转换为

以下为引用:

// internal transformation under V2
public ref class R
{
public:
  void Finalize() {  Console::WriteLine( "I am the R::finalizer()!" ); }
};
  



    为了支持从老版本的Managed C++中将代码移植出来,MS还准备开发一个自动转换工具,将原本显式定义的Dispose()方法转换为析构函数;将原本定义的析构函数转换为!前缀支持的显式Finalize函数定义。

    有趣的是,这一实现思路与Delphi.NET完成类似析构函数语义的思路很相似,有兴趣进一步了解的朋友可以参考这篇文章

    Object Destructors and Finalizers in .NET Using C# and Delphi for .NET

    几位Borland系统的老兄也针对相关问题有一些不错的评论:

    Allen Bauer 的 The rules have not changed

    Nick Hodges 的 On Finalizers at Filafel
--
.    生命的意义在于   /\   ____\ /\_ \   /\_\          http://flier.yeah.net.                            
.        希望         \ \  \___/_\/\ \   \/_/__     __    _ _★              .  
.        工作          \ \   ____\\ \ \    /\  \  /'__`\ /\`'_\              .  
.      爱你的人         \ \  \___/ \ \ \___\ \  \/\ __// \ \ \/              .  
.     和你爱的人         \ \___\    \ \_____\ \__\ \____\ \ \_\              .  
.        ……             \/___/     \/_____/\/__/\/____/  \/_/ @nsfocus.com.  


※ 来源:·BBS 水木清华站 smth.org·[FROM: 211.167.254.*]
上一篇
返回上一页
回到目录
回到页首
下一篇



W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
78.125ms