惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

B
Blog
I
InfoQ
Y
Y Combinator Blog
The Last Watchdog
The Last Watchdog
博客园_首页
The Cloudflare Blog
博客园 - 【当耐特】
Engineering at Meta
Engineering at Meta
罗磊的独立博客
月光博客
月光博客
V
V2EX
大猫的无限游戏
大猫的无限游戏
腾讯CDC
GbyAI
GbyAI
云风的 BLOG
云风的 BLOG
Stack Overflow Blog
Stack Overflow Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Attack and Defense Labs
Attack and Defense Labs
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Google Online Security Blog
Google Online Security Blog
B
Blog RSS Feed
Webroot Blog
Webroot Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
N
Netflix TechBlog - Medium
量子位
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Vercel News
Vercel News
C
CERT Recently Published Vulnerability Notes
人人都是产品经理
人人都是产品经理
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Recent Announcements
Recent Announcements
Cyberwarzone
Cyberwarzone
G
Google Developers Blog
H
Heimdal Security Blog
MyScale Blog
MyScale Blog
The Register - Security
The Register - Security
博客园 - 三生石上(FineUI控件)
小众软件
小众软件
aimingoo的专栏
aimingoo的专栏
T
Tenable Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
O
OpenAI News
C
Check Point Blog
Forbes - Security
Forbes - Security
SecWiki News
SecWiki News
K
Kaspersky official blog
The GitHub Blog
The GitHub Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
F
Full Disclosure
阮一峰的网络日志
阮一峰的网络日志

博客园 - Justin Shen

[.Net 4.0]泛型的协变,以及高阶函数对泛型的影响 Part 1 随笔 - WCF and Data Service - Justin Shen 面向对象语言中的Environment和Binding 元数据 有多少东西需要学习? [电子书下载]Dissecting a C# Application: Inside SharpDevelop [MSDNTV]Don Box再次出击 :) 追踪你的时间使用状况 听说《csdn开发高手》停刊了 在nant中改变编译的目标平台 让使用MSN就像访问网页一样容易! System.String是不可变的字符串吗? 对中国计算机大学教育的一些牢骚 [VS2005]做了两个Code Expansion用的Code Snippet。 VC2005中依然没有Refactoring和Code Expansion. [VS2005 Tip]定制Code Expansion。 [C++/CLI]在栈上声明Reference Type 用80386汇编来编写asp.net页面。 关于C#泛型中的new()约束
[C++/CLI] 析构函数等于IDisposable::Dispose()方法
Justin Shen · 2004-10-14 · via 博客园 - Justin Shen

在以前的一篇帖子里我曾提到在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语句的经验与教训之后,为显式释放资源提供了一个完美的解决方案。