C++之竹

无论是太阳下,还是风雨中,都要成长!

常用链接

统计

最新评论

Singleton模式——C++应用(四)

 在前面的例子中,我们看到:采用 new 来为单件对象分配空间,如果采用手动调用 delete 或封装了 delete 的 Release 操作,一旦遇到全局对象的析构有调用单件对象,就会使得无法在代码中找到适合释放单件对象的时机。那么,是否可以让系统来自动选择时机,调用释放呢?如果可以,又该怎么在代码中构建单件对象的自动释放机制呢? 对这两个问题,在进行了一番思考和尝试后,终于找到了答案 —— 内建只有一个析构方法的结构体,定义一个静态的该结构体的变量,并在结构体的析构中释放单件对象。下文将就此给出 Demo,还望有高手能给出更好的方案。(从前面内容,我们已经知道,单件对象的指针通过静态类成员变量进行存储,并通过 new 分配的方式,存在在着线程安全的问题。同理,下面Demo的单件类A在多线程环境使用时,自然也存在线程安全的问题。)

 Demo代码如下:

  1// Singleton demo_2: Singleton instance is created by new.
  2// [A does not support multithreading, but C support.] + [delete instance automatically]
  3
  4#include <Windows.h>
  5#include <iostream>
  6
  7class A 
  8{
  9private:
 10    static struct A_RELEASER {
 11        ~A_RELEASER() {
 12            std::cout << "Release singleton of A. {{" << std::endl;
 13            if (ms_pInstance != NULL)
 14            {
 15                delete ms_pInstance;
 16                ms_pInstance = NULL;
 17            }

 18            std::cout << "}} Release singleton of A." << std::endl;
 19        }

 20    }
 ms_autoReleaser;
 21
 22    static A* ms_pInstance;
 23
 24public:
 25    static A& GetInstance();
 26
 27private:
 28    A() : m_nStat1(-1), m_nStat2(-1{
 29        m_nStat1 = 0;
 30        std::cout << "Construct A" << std::endl;
 31        m_nStat2 = 0;
 32    }

 33    A(const A&);
 34
 35public:
 36    ~A() {
 37        m_nStat1 = 0;
 38        std::cout << "Destruct A" << std::endl;
 39        m_nStat2 = 0;
 40    }

 41
 42    void Do() {
 43        ++m_nStat1;
 44        ++m_nStat2;
 45        std::cout << "Called Do() by object of A. [" 
 46            << m_nStat1 << "" 
 47            << m_nStat2 << "]" 
 48            << std::endl;
 49    }

 50
 51private:
 52    int m_nStat1;
 53    int m_nStat2;
 54}
;
 55
 56class C
 57{
 58private:
 59    static struct C_RELEASER {
 60        ~C_RELEASER() {
 61            std::cout << "Release singleton of C. {{" << std::endl;
 62            delete &GetInstance();
 63            std::cout << "}} Release singleton of C." << std::endl;
 64        }

 65    }
;
 66
 67public:
 68    static C& GetInstance();
 69
 70private:
 71    C() : m_nStat(-1{
 72        std::cout << "Construct C" << std::endl;
 73        m_nStat = 0;
 74    }

 75    C(const C&);
 76
 77public:
 78    ~C() {
 79        std::cout << "Destruct C" << std::endl;
 80        m_nStat = 0;
 81    }

 82
 83    void Do() {
 84        ++m_nStat;
 85        std::cout << "Called Do() by object of C. [" 
 86            << m_nStat << "]" 
 87            << std::endl;
 88    }

 89
 90private:
 91    int m_nStat;
 92}
;
 93
 94class B
 95{
 96public:
 97    B(int nID) : m_nID(nID) {
 98        std::cout << "Construct B: " << m_nID << std::endl;
 99        A::GetInstance().Do();
100        C::GetInstance().Do();
101    }

102    ~B() {
103        std::cout << "Destruct B: " << m_nID << std::endl;
104        A::GetInstance().Do();
105        C::GetInstance().Do();
106    }

107
108private:
109    int m_nID;
110}
;
111
112static B gs_B0(0);
113B g_B1(1);
114
115A* A::ms_pInstance = NULL;
116A::A_RELEASER A::ms_autoReleaser;
117A& A::GetInstance()
118{
119    if (NULL == ms_pInstance)
120    {
121        ms_pInstance = new A;
122    }

123
124    return *ms_pInstance;
125}

126
127C& C::GetInstance()
128{
129    static C_RELEASER s_autoReleaser;
130    static C* s_pInstance = new C;
131
132    return *s_pInstance;
133}

134
135static B gs_B2(2);
136B g_B3(3);
137
138int main(int argc, char * argv[])
139{
140    std::cout << "Enter main" << std::endl;
141    A::GetInstance().Do();
142    C::GetInstance().Do();
143    
144    system("pause");
145    return 0;
146}

147

运行后的结果:

 

综合Demo代码和运行结果,我们可以看到,对于单件类A的对象释放者采用了类的静态成员的方式来定义,其结果是,单件类A的对象释放时机仍然不对。

再看C,代码中new 所得的对象指针交由一局部静态变量以保证 new 只会执行一次(从而保证了线程安全), 而单件对象的释放者就定义在紧挨 new 的前面(事实上,也可以定义在紧挨 new 的后面)。接着是执行结果,完全OK! 哈哈~,值得推荐的第二种C++单件类构建模式终于也出炉了,那就是上例Demo中,单件类C的构建模式。

 

至此,《Singleton模式——C++应用》全部完成,因为还是第一次写技术博客,写得不好,还请各位看官见谅!

嗯~,突然发现,我漏写了对这全部四篇内容的一个总结,……还是算了,就请各位原谅我这次的偷懒咯!~

 

posted on 2012-03-14 01:07 青碧竹 阅读(329) 评论(0)  编辑 收藏 引用 所属分类: 设计模式


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理