http://blog.csdn.net/windboyzsj/article/details/2790485

最近接触的一个项目要用到单件模式,我像往常一样哒哒(敲击键盘ing)一个单件模式的典型结构很快就出现在我的面前:

  1. class Singleton
  2. {
  3. public:
  4. ~Singleton(){}
  5. static Singleton* Instance()
  6. {
  7. if (_instance == NULL)
  8. {
  9. _instance = new Singleton();
  10. }
  11. return _instance;
  12. }
  13. private:
  14. Singleton(){}
  15. static Singleton* _instance;
  16. };
  17. Singleton* Singleton::_instance = NULL;

不知道为什么,这次突然觉得new这个单词太耀眼了,熟悉c++的程序员都知道,有new就离不开delete,既然单件模式共用一个实例,那么这个实例什么时候释放呢。带着好奇我在它的析构函数加了个打印语句,但由于new操作是在堆里分配内存,估计它的析构函数不会被调用,而试验结果确实如此。这样一来那单件模式的析构函数不是完全废了吗,如果这个单件类还有指针成员用new分配了空间那又应该在哪里释放?单件的实例又应该如何释放。当然,我们可以在程序退出时通过 delete Singleton::Instance(); 来释放内存并触发析构函数。但这样一来,写好的类给别人用时就要叮嘱别人,用完后一定要释放- - !,再说别人不一定记得...有没有一种机制让单件模式自动释放?百度,google很久,发现关注这个问题的寥寥无几,但还是给我找到了一篇文章让我再次领略C++的灵活。按此文章大概把代码修改如下;

  1. class Singleton
  2. {
  3. public:
  4. ~Singleton(){}
  5. static Singleton* Instance()
  6. {
  7. if (_instance == NULL)
  8. {
  9. _instance = new Singleton();
  10. }
  11. return _instance;
  12. }
  13. private:
  14. Singleton(){}
  15. static Singleton* _instance;
  16. class Cleaner
  17. {
  18. public:
  19. Cleaner(){}
  20. ~Cleaner()
  21. {
  22. if(Singleton::Instance())
  23. delete Singleton::Instance();
  24. }
  25. };
  26. static Cleaner clr;
  27. };
  28. Singleton* Singleton::_instance = NULL;

事先声明我用VC6.0编译上面的代码(当然我有加一些测试代码)发现,clr并没有实例化,当然也就是没有析构了,暂时不清楚为什么,但这里的设计却是很值得品味。它通过一个内嵌类和一个静态成员来实现了自动释放的机制,相当于为单件加了个垃圾回收器。整个设计最巧妙的地方在于static Cleaner clr;这个声明,由于是静态成员,系统会在栈里分配内存,回收工作也就由系统自动完成了。这个思路另我想起了通过静态变量来实现类的静态构造函数,他们都有异曲同工之处。至于私有的内嵌类主要是防止单件类的专用垃圾筒被打扰...

虽然上面代码没有达到目的,但根据他的思路,可以做一下调整,把Cleaner的实例化延迟,下面贴出整个测试代码,一下代码在VC6编译通过。

  1. #include <iostream.h>
  2. class Singleton
  3. {
  4. public:
  5. ~Singleton(){cout<<"singleton deconstruct"<<endl;}
  6. static Singleton* Instance()
  7. {
  8. if (_instance == NULL)
  9. {
  10. _instance = new Singleton();
  11. static Cleaner cl; //延迟到这里
  12. }
  13. return _instance;
  14. }
  15. void Print(char* str)
  16. {
  17. cout<<"singleton print:"<<str<<endl;
  18. }
  19. private:
  20. Singleton(){cout<<"singleton construct"<<endl;}
  21. static Singleton* _instance;
  22. class Cleaner
  23. {
  24. public:
  25. Cleaner(){cout<<"cleaner construct"<<endl;}
  26. ~Cleaner()
  27. {
  28. cout<<"cleaner deconstruct"<<endl;
  29. if(Singleton::Instance())
  30. delete Singleton::Instance();
  31. }
  32. };
  33. };
  34. Singleton* Singleton::_instance = NULL;
  35. int main(int argc, char* argv[])
  36. {
  37. Singleton::Instance()->Print("print 1");
  38. Singleton::Instance()->Print("print 2");
  39. return 0;
  40. }

关于C++单件模式释放对象的更多相关文章

  1. 设计模式之单件模式(Singleton Pattern)

    一.单件模式是什么? 单件模式也被称为单例模式,它的作用说白了就是为了确保“该类的实例只有一个” 单件模式经常被用来管理资源敏感的对象,比如:数据库连接对象.注册表对象.线程池对象等等,这种对象如果同 ...

  2. 单件模式Singleton来控制窗体被重复或多次打开

    本文转载:http://blog.csdn.net/a0700746/article/details/4473796 一般在百度搜一下,会出来一下内容,看来很好用.Singleton很方便的一个用处就 ...

  3. Java设计模式——线程安全的单件模式

    单件模式,也称单例模式,用以创建独一无二的.只能有一个实例的对象. 单件模式的类图是所有模式的类图中最简单的--只有一个类.尽管从类设计的视角来看单件模式很简单,但是实现上还是会遇到一些问题,本文着重 ...

  4. C#设计模式——单件模式

    一.为何需要单件模式 需求 我们开发了一个大型的项目,其中存在许多的工具类.但是其中很多的工具类我们并不是经常使用得到,甚至 一次都不会使用.但是这些工具类都是静态的类,会消耗很多的内存,即使一次都不 ...

  5. [设计模式] javascript 之 单件模式

    单件模式说明 1. 说明:单件模式,就是静态化的访问中已经实例化的对象,这个对象只能通过一个唯一的入口访问,已经实例或待实例化的对象:面向对象语言如Java, .Net C#这样的服务端动态语言里,能 ...

  6. .NET设计模式(2):单件模式(Singleton Pattern)

    转载:http://terrylee.cnblogs.com/archive/2005/12/09/293509.html 单件模式(Singleton Pattern) --.NET设计模式系列之二 ...

  7. NET设计模式(2):单件模式(Singleton Pattern)[转载]

    单件模式(Singleton Pattern) ——.NET设计模式系列之二 Terrylee,2005年12月07日 概述 Singleton模式要求一个类有且仅有一个实例,并且提供了一个全局的访问 ...

  8. 设计模式(二)单件模式Singleton(创建型)

    SINGLETON(单件)—对象创建型模式 几乎所有面向对象的程序中,总有一些类的对象需要是唯一的,例如,通过数据库句柄到数据库的连接是独占的.您希望在应用程序中共享数据库句柄,因为在保持连接打开或关 ...

  9. 9、Cocos2dx 3.0游戏开发三查找值小工厂方法模式和对象

    重开发人员的劳动成果,转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/27704153 工厂方法模式 工厂方法是程序设计中一个 ...

随机推荐

  1. 深入理解JVM内存模型

    1.程序计数器在虚拟机的概念模型里字节码解释器工作时就是通过改变 这个计数器的值来选取下一条需要执行的字节码指令,分支.循环.跳转.异常处理. Java 虚拟机的多线程是通过线程轮流切换并分配处理器执 ...

  2. css文本属性

    CSS1&2中的文本属性 属性 版本 简介 text-indent CSS1 检索或设置对象中的文本的缩进 letter-spacing CSS1 检索或设置对象中的文字之间的间隔 word- ...

  3. Nodejs编码转化问题

    目前Node.js仅支持hex.utf8.ascii.binary.base64.ucs2几种编码的转换.对于GBK,GB2312等编码,Nodejs自带的toString()方法不支持,因此中文转化 ...

  4. java中throw和throws的区别

    throw和throws的区别: throws 用在方法声明后面,跟的是异常类名 可以跟多个异常类名,用逗号隔开 表示抛出异常,由该方法的调用者来处理 throws表示出现异常的一种可能性,并不一定会 ...

  5. OpenWRT连接OPENVPN的教程

    这是相当基本没有任何web界面,只是几个命令如何运行OpenWRT的 OpenVPN的例子. OpenWRT的设置更复杂,所以这个教程仅供爱好者和经验的用户使用参考. 本教程假定您有OpenWRT的安 ...

  6. android text

    "@you bang--- go on -------" 需要做分享内容,前面有段格式固定写死,同时颜色为灰色:后面的内容可以编辑,颜色为黑色,同时支持多行 有人用textview ...

  7. Android中轴旋转特效实现,制作别样的图片浏览器

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/10766017 Android API Demos中有很多非常Nice的例子,这些例 ...

  8. 使用adb 查询data/data下的数据库

    1.用cmd打开adb 2.输入adb shell 3.cd到数据库所在目录 4.输入sqlite3 person.db(person.db为要操作的db名称,根据需要修改) 5.输入sql语句(每个 ...

  9. android shape的使用

    文章出自:http://www.cnblogs.com/cyanfei/archive/2012/07/27/2612023.html <?xml version="1.0" ...

  10. Android性能优化方法(四)

    在一个应用程序中,一般都会存在多个Activity,每个Activity对应着一个UI布局文件.一般来说,为了保持不同窗口之间的风格统一,在这些UI布局文件中,几乎肯定会用到很多相同的布局.如果我们在 ...