`
阿尔萨斯
  • 浏览: 4168206 次
社区版块
存档分类
最新评论

C++ local class 的用途:finalizer 手法

 
阅读更多
<iframe align="center" marginwidth="0" marginheight="0" src="http://www.zealware.com/csdnblog.html" frameborder="0" width="728" scrolling="no" height="90"></iframe>
在有异常的程序里面,函数的出口变得难以捉摸起来,这是大家都知道的了。但是很多时候,我们希望函数在退出之前能够一定完成某些事情,在 Java 里面,我们用 try...finally 来干这件事;而在 C++ 里面,我们有 RAII 这个好东西。不过有的时候,RAII 显得有些笨拙,如果我们希望一个函数无论如何在退出之前都要输出一个警告到控制台,难道还要为了它专门写一个类么?这不但让代码分散难于理解,而且“污染“了命名空间。

还好,我们有 local class ,这个东西看起来没什么用,但是用在这里却很合适。对于下面的这段代码,要是不用 RAII ,完成“每次退出都要执行”的动作几乎是不可能的:

#include <iostream></iostream>
#include <exception></exception>

int func(int i)
{
try
{
switch (i)
{
case 1:
throw "i = 1";
case 2:
throw std::exception("i = 2");
case 3:
throw 3;
default:
throw std::runtime_error("default");
}

int ret = 1 / i;
return ret;
}
catch(std::runtime_error& e)
{
std::cout
}

return 0;
}

int main()
{
for ( int i = 0; i
try
{
std::cout
}
catch(...)
{
std::cout
}
}

输出:

runtime_error: default
func(0): 0
func(1) throws exception.
func(2) throws exception.
func(3) throws exception.
runtime_error: default
func(4): 0

而用常规的 RAII 又不太必要,这就是 local class 显身手的地方:

#include <iostream></iostream>
#include <exception></exception>

int func(int i)
{
struct finally
{
~finally(){ std::cout
}finalizer;

try
{
switch (i)
{
case 1:
throw "i = 1";
case 2:
throw std::exception("i = 2");
case 3:
throw 3;
default:
throw std::runtime_error("default");
}

int ret = 1 / i;
return ret;
}
catch(std::runtime_error& e)
{
std::cout
}

return 0;
}

int main()
{
for ( int i = 0; i
try
{
std::cout
}
catch(...)
{
std::cout
}
}

输出:

runtime_error: default
func() is exiting
func(0): 0
func() is exiting
func(1) throws exception.
func() is exiting
func(2) throws exception.
func() is exiting
func(3) throws exception.
runtime_error: default
func() is exiting
func(4): 0

这其实也是变相的 RAII ,只不过比起“常规”实现,有一些好处:
1. 代码集中,便于理解
2. 不会污染命名空间
3. 可以对所有的 finalizer 采取统一命名
...
应该还有一些,不说了。





分享到:
评论

相关推荐

    .NET 常见问答:完成器(Finalizer)、程序集名、方法信息等等

    在我的类中何时需要实现一个完成器?我是否一定要实现完成器,或者只是在我控制着 非托管资源时才需要实现它?我是否一定要在我的完成器中实现 IDisposable 接口?...关键字:finalizer,assembly names,methodinfo

    teclast-f5-ubuntu-finalizer:当前的HWSW KernelSystemACPI修改,以获取$ 400的Dream Ubuntu Linux笔记本电脑

    teclast-f5-ubuntu-finalizer:当前的HWSW KernelSystemACPI修改,以获取$ 400的Dream Ubuntu Linux笔记本电脑

    flexipatch-finalizer:自定义预处理器,用于从flexipatch版本中删除未选择的补丁,从而保留最终的补丁版本

    flexipatch-finalizer是一个自定义预处理器,它使用相同的配置文件,并剥离所有未使用代码的flexipatch构建,从而保留应用了选定补丁的软件构建。 该终结器的示例flexipatch构建可用于: :warning: 请务必注意,...

    使用mimalloc的简单保守GC-C/C++开发

    migc小型简单的库,使用mimalloc API实现保守的GC。...有:migc_add_roots和migc_delete_roots用于添加或删除指针范围以扫描潜在的指针,migc_register_finalizer用于在死对象上调用终结器。 快速分配。 什么时候

    finalizers:愚蠢的终结者

    愚蠢的终结者建造go build 跑# List all objects blocked by a finalizer./finalizers# List all objects with finalizers./finalizers --all例子./finalizersNAMESPACE NAME APIVERSION KIND FINALIZERSp-nf5gh ...

    基于.NET程序默认启动线程数讲解

    调试器帮助线程3.Finalizer线程 代码如下:class Program { static void Main(string[] args) { Console.WriteLine(“Main thread: {0}”, Thread.CurrentThread.ManagedThreadId); Console.ReadKey(); } } ...

    puppet-provisioner

    Aminator 的 Puppet Provisioner 基于 Archie Cowan 的初步... 例如: ec2_puppet_debian: cloud: ec2 distro: debian provisioner: puppet volume: linux blockdevice: linux finalizer: tagging_ebs ec2_puppet_redha

    java.lang.ref 简要一览

    NULL 博文链接:https://chong-zh.iteye.com/blog/1603616

    免费wordpress采集工具.zip

    wordpress免费采集和批量发布工具,该工具是147免费采集流出版本,支持wp等多CMS采集,以及支持多关键词批量采集多新闻源,可以做到同时批量采集并批量伪原创然后批量定时发布。

    免费迅睿CMS采集工具.zip

    迅睿免费采集和批量发布工具,该工具是147免费采集流出版本,支持迅睿等多CMS采集,以及支持多关键词批量采集多新闻源,可以做到同时批量采集并批量伪原创然后批量定时发布。

    python3.6.5参考手册 chm

    PEP 495: Local Time Disambiguation PEP 529: Change Windows filesystem encoding to UTF-8 PEP 528: Change Windows console encoding to UTF-8 PEP 520: Preserving Class Attribute Definition Order PEP ...

    week-1:计算+ C#

    constructor, method, finalizer/destructor block 修饰符 static =在应用程序启动时创建的单个实例,可以在运行时更改值 const =应用程序启动时的单个实例,运行时无法更改值 readonly =构造时的单个实例,设置后...

    dirty_scheduler:R17.3 +的Erlang脏调度程序示例

    dirty_scheduler 不要忘记使用“ --enable-dirty-schedulers”... 从Erlang 17.03开始,enif_schedule_dirty_nif,enif_schedule_dirty_nif_finalizer和enif_dirty_nif_finalizer被删除(erl_nif.h)。 更多信息: :

    gradle-circle样式::rocket::rocket::rocket:移至基线

    Gradle圈样式Gradle插件可总结失败的Gradle构建,和失败进行特殊处理。快速开始将以下内容添加到项目的... 然后,它会自动为Checkstyle和FindBugs插件启用XML输出,并添加一个finalizer任务,以使用CircleCI期望的JUni

    C#析构函数

    析构函数 finalizer destructor 整理的关于析构函数的描述以及介绍

    关于finalize机制和引用、引用队列的用法详解

    C++有析构函数这个东西,能够很好地在对象销毁前做一些释放外部资源的工作,但是java没有。Object.finalize()提供了与析构函数类似的机制,但是它不安全、会导致严重的内存消耗和性能降低,应该避免使用。best ...

    MAT工具(基于Eclipse的内存分析工具)+MAT工具使用说明.docx

    (2)对象报表,对可颖对象的分析,如字符串是否定义重了,空的collection、finalizer以及弱引用等。 我这里选择的是查看内存报表,以下是截的简略图: 通过报表展示,蛮清楚的,下面还有详细的说明,这里就没有...

    migc:使用mimalloc的简单保守GC

    有: migc_add_roots和migc_delete_roots用于添加或删除指针范围以扫描潜在的指针, migc_register_finalizer用于在死对象上调用终结器。 快速分配。 当在多个线程中运行migc堆的多个实例时,该库可能比BDWGC快得多...

    try-lua:纯 Lua 相当于 lua-try (https

    纯 Lua 相当于 lua-try ( ),它同样基于 newtry、protect 和 try 功能。... #关于newtry()/protect() 简而言之,您可以使用 can newtry(finalizer)来制作一个函数包装器,该包装器可以应用于使用惯用的 Lu

Global site tag (gtag.js) - Google Analytics