苏林

一程序, 一世界

用户操作
[即时聊天] [发私信] [加为好友]
苏林ID:Slin000
92028次访问,排名1021(-1)好友86人,关注者97
仔细思考,踏实做事
MSN:hotsoo@hotmail.com
按关键字聊天的小程序,欢迎试用:
http://6t6t.xicp.net
Slin000的文章
原创 33 篇
翻译 0 篇
转载 0 篇
评论 565 篇
苏林的公告

诚邀朋友们试用
10楼聊天室
按关键字聊天,找到有共同话题的人!

欢迎给我留言,谢谢

最近评论
zoubin1986:看见电脑小白几个字我就想发飙!
自己玩过几年开发就当自己成仙了~
听人说过一句话:上海人歧视外地人就像巴黎人瞧不起全世界的人一样~~~~~
劣根性,就懂内讧!就懂划分阶级!你也是打娘胎里出来的,现在反倒看不起“刚出生”的了。

其实大家若都有钱谁又非得用盗版?有需求才会有市场!软件开发者们!是你们拱手将中国让给了微软!怎么就不懂奋起直追,而非……
hjdl60:我就正在看ogre3D真的很精彩!大师就是大师,设计模式的应用,整体框架的构思无不散发着智慧!
lonelybug:你放心,肯定不会。
l_lengqing:Javascript在网页设计中很有威力,
以前没做页面没注意,做了以后才发现用它很好
zabaglione:应该不会成为主流。这种解释型的语言。
文章分类
    收藏
      相册
      友情链接
      爱生活,爱读书--杨福川 图灵
      存档
      订阅我的博客
      XML聚合  FeedSky
      订阅到鲜果
      订阅到Google
      订阅到抓虾
      订阅到BlogLines
      订阅到Yahoo
      订阅到GouGou
      订阅到飞鸽
      订阅到Rojo
      订阅到newsgator
      订阅到netvibes

      原创 C++中单例模式对象的释放控制收藏

      新一篇: JSON 还是 XML? | 旧一篇: 巨人的美女营销和盛大的美女游戏

       
      单例模式也称为单件模式、单子模式。使用单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享有很多地方需要这样的功能模块,如系统的日志输出等。
       
      单例模式有许多种实现方法,在C++中,甚至可以直接用一个全局变量做到这一点,但这样的代码显得很不优雅。《设计模式》一书中给出了一种很不错的实现,定义一个单例类,使用类的私有静态指针变量指向类的唯一实例,并用一个公有静态方法获取该实例。如下面的类定义:
       
      class CSingleton:
      {
          // 其它成员
      public:
          static CSingleton * GetInstance()
          {
              if (m_pInstance == NULL)
                  m_pInstance = new CSingleton();
              return m_pInstance;
          }
       
      private:
          CSingleton(){};
          static CSingleton * m_pInstance;
      }
      单例类CSingleton有以下特征:
      Ø         它有一个指唯一实例的静态指针m_pInstance,并且是私有的。
      Ø         它有一个公有的函数,可以获取这个唯一的实例,并在需要的时候创建该实例。
      Ø         它的构造函数是私有的,这样就不能从别处创建该类的实例。
       
      大多时候,这样的实现都不会出现问题。有经验的读者可能会问,m_pInstance指向的空间什么时候释放呢?更严重的问题是,这个实例的析构操作什么时候执行?
       
      如果在类的析构行为中有必须的操作,比如关闭文件,释放外部资源,那么上面所示的代码无法实现这个要求。我们需要一种方法,正常地删除该实例。
       
      可以在程序结束时调用GetInstance并对返回的指针调用delete操作。这样做可以实现功能,但是不仅很丑陋,而且容易出错。因为这样的附加代码很容易被忘记,而且也很难保证在delete之后,没有代码再调用GetInstance函数。
       
      一个妥善的方法是让这个类自己知道在合适的时候把自己删除。或者说把删除自己的操作挂在系统中的某个合适的点上,使其在恰当的时候自动被执行。
       
      我们知道,程序在结束的时候,系统会自动析构所有的全局变量。事实上,系统也会析构所有的类的静态成员变量,就像这些静态成员也是全局变量一样。利用这个特征,我们可以在单例类中定义一个这样的静态成员变量,而它的唯一工作就是在析构函数中删除单例类的实例。如下面的代码中的CGarbo类(Garbo意为垃圾工人):
      class CSingleton:
      {
          // 其它成员
      public:
          static CSingleton * GetInstance(){。。。}
      private:
          CSingleton(){};
          static CSingleton * m_pInstance;
       
          class CGarbo // 它的唯一工作就是在析构函数中删除CSingleton的实例
          {
          public:
              ~CGarbo()
              {
                  if (CSingleton::m_pInstance)
                      delete CSingleton::m_pInstance;
              }
          };
       
          static CGarbo Garbo; // 定义一个静态成员,在程序结束时,系统会调用它的析构函数
      }
       
      类CGarbo被定义为CSingleton的私有内嵌类,以防该类被在其它地方滥用。
       
      在程序运行结束时,系统会调用CSingleton的静态成员Garbo的析构函数,该析构函数会删除单例的唯一实例。
       
      使用这种方法释放单例对象有以下特征:
      Ø         在单例类内部定义专有的嵌套类。
      Ø         在单例类内定义私有的专门用于释放的静态成员。
      Ø         利用程序在结束时析构全局变量的特性,选择最终的释放时机。
      Ø         使用单例的代码不需要任何操作,不必关心对象的释放。
       
      作者:苏林
       

      发表于 @ 2008年04月09日 17:23:00|评论(loading...)|编辑

      新一篇: JSON 还是 XML? | 旧一篇: 巨人的美女营销和盛大的美女游戏

      评论

      #哈哈哈 发表于2008-04-10 11:45:03  IP: 211.100.255.*
      为什么不直接定义一个 static CSingleton m_Instance;
      #zx77 发表于2008-04-10 12:13:01  IP: 124.77.104.*
      MFC里就有一个theApp对象,就是一个全局的对象,非要new一个的话也可以考虑智能指针.
      #学徒 发表于2008-04-10 14:09:13  IP: 61.141.231.*
      相对专门用个垃圾工,这样写有什么问题吗?
      static CSingleton * GetInstance()
      {
      if (m_pInstance == NULL)
      {
      static CSingleton _pInstance;
      m_pInstance = &_pInstance;
      }
      return m_pInstance;
      }
      #arthurlee 发表于2008-04-10 14:23:28  IP: 58.33.57.*
      需要考虑两个问题:

      1. 线程安全
      单件一般都是在多线程环境下来应用,所以需要保证线程安全。

      2. 如果单件在DLL中实例化,即代码被封装在DLL中,供其他程序来调用,则使用析构函数来释放有死锁的危险性,这个要看这个单件在析构时,是否会调用wait系列函数、sleep函数等会导致死锁的win32调用。
      请参见

      Some reasons not to do anything scary in your DllMain
      http://blogs.msdn.com/oldnewthing/archive/2004/01/27/63401.aspx

      Best Practices for Creating DLLs
      http://www.microsoft.com/whdc/driver/kernel/DLL_bestprac.mspx
      #C 发表于2008-04-10 16:38:06  IP: 218.18.17.*
      static CSingleton pInstance ;
      static CSingleton * GetInstance()
      {
      return &pInstance ;
      }
      #bamboo1998 发表于2008-04-11 10:27:35  IP: 124.193.148.*
      static CGarbo Garbo; // 定义一个静态成员,在程序结束时,系统会调用它的析构函数

      程序都结束了,还要释放什么内存啊?多此一举。
      #antimatterworld 发表于2008-04-11 14:40:37  IP: 60.20.20.*
      类内部声明一个静态实例不行吗?
      #fansyp 发表于2008-04-11 17:09:09  IP: 60.191.25.*
      混迹江湖需要经验,这种代码基本上没有用。
      #bamboo1998 发表于2008-04-11 17:27:27  IP: 124.193.148.*
      还能上头条,csdn真是的。
      #大侠 发表于2008-04-12 17:38:08  IP: 123.112.100.*
      单态的析构不仅仅是释放内存,也许还有其他操作呢
      #msdn47 发表于2008-04-12 17:48:17  IP: 221.11.46.*
      问题太多了!
      看看这个:

      非完美C++ Singleton实现:
      http://www.cppblog.com/ant/archive/2007/09/07/31445.html

      http://www.cppblog.com/ant/archive/2007/09/07/31786.html
      #yjlh1234 发表于2008-04-12 20:13:52  IP: 58.244.68.*
      析构释放后要将指针置空..
      多线程时 ..这个版本是有问题的...
      要使用双重检测...!!
      问题多.....
      #zz 发表于2008-04-13 16:10:39  IP: 220.160.151.*
      主要问题在于 “时机” 很难确定。比如如你所说的,一个日志单体,当程序退出时,往往是许多其它对象在释放前,调用log输出本次运行最后一条日志的时机,而这个时机往往也正是在一些类的析构函数里。如同没法保证各个全局的初始化次序一样,C++无法保证各个全局变量(包括例中使用的类静态成员数据)的析构次序。假设log通过文中的方法被析构(并重新置0: m_pInstance = 0)了,而之后再有代码调用,则m_pInstance再次被创建。如果不被置0,如文中的代码,则会出现段错误。
      #wzh19831221 发表于2008-04-14 09:43:55  IP: 202.108.128.*
      感觉没有什么太大的意义啊??
      #aheroofeast 发表于2008-04-14 13:10:14  IP: 10.51.41.*
      Modern C++ Design里有一章专门讨论singleton
      发表评论  


      登录
      Csdn Blog version 3.1a
      Copyright © 苏林