C++单例模式实例

定义:在某些情况下,我们设计中的对象只需要一个,比方说:线程池(threadpool)、缓存(cache)、对话框、处理偏好设置和注册表对象、日志对象、充当打印机、显卡等设备的驱动程序的对象等。事实上,这类对象只能有一个实例,如果制造出多个实例,就会导致许多问题产生。
这里要说的单件模式就能确保一个类只有一个实例,并提供一个全局访问点。
在C++中实现如下:
实现1:
 1 #include <iostream>
 2 using namespace std;
 3  
 4 class CSingleton
 5 {
 6 public:
 7     static CSingleton* getInstance();
 8     static void cleanInstance();
 9     int getValue();
10     void setValue(int iValue);
11 private:
12     int m_iValue;
13     static CSingleton* m_pSingleton;
14     CSingleton();
15     ~CSingleton();
16 };
17  
18 CSingleton* CSingleton::m_pSingleton = NULL;
19  
20 CSingleton::CSingleton()
21 {
22     cout << "Constructor" << endl;
23 }
24  
25 CSingleton::~CSingleton()
26 {
27     cout << "Destructor" << endl;
28 }
29  
30 CSingleton* CSingleton::getInstance()
31 {
32     if (NULL == m_pSingleton)
33     {
34         m_pSingleton = new CSingleton();
35     }
36     return m_pSingleton;
37 }
38  
39 void CSingleton::cleanInstance()
40 {
41     delete m_pSingleton; m_pSingleton = NULL;
42 }
43  
44 int CSingleton::getValue()
45 {
46     return m_iValue;
47 }
48  
49 void CSingleton::setValue(int iValue)
50 {
51     m_iValue = iValue;
52 }
53  
54 int main()
55 {
56     CSingleton* pSingleton1 = CSingleton::getInstance();
57     CSingleton* pSingleton2 = CSingleton::getInstance();
58     pSingleton1->setValue(123);
59     if (pSingleton1->getValue() == pSingleton2->getValue())
60     {
61         cout << "Two objects is the same instance" << endl;
62     }
63     else
64     {
65         cout << "Two objects isn't the same instance" << endl;
66     }
67  
68     CSingleton::cleanInstance();
69     return 0;
70 }
相信大多数的同仁都喜欢使用上边这种单件模式的实现方法,如果在单线程的情况下,是没有问题的,但如果是多线程,那么就极有可能会返回两个不同的对象,在调用CSingleton::getInstance的时候,两个线程如果都同时运行完if判断,而又还没有调用到构造函数的话,想象下后果吧。那该怎么办呢?看下边这个实现吧。
实现2:
 1 #include <iostream>
 2 using namespace std;
 3  
 4 class CSingleton
 5 {
 6 public:
 7     static CSingleton* getInstance();
 8     static void cleanInstance();
 9     int getValue();
10     void setValue(int iValue);
11 private:
12     int m_iValue;
13     static CSingleton* m_pSingleton;
14     CSingleton();
15     ~CSingleton();
16 };
17  
18 // 在进程运行开始就实例化该单件,又称“急切”创建实例
19 CSingleton* CSingleton::m_pSingleton = new CSingleton();
20  
21 CSingleton::CSingleton()
22 {
23     cout << "Constructor" << endl;
24 }
25  
26 CSingleton::~CSingleton()
27 {
28     cout << "Destructor" << endl;
29 }
30  
31 CSingleton* CSingleton::getInstance()
32 {
33     return m_pSingleton;
34 }
35  
36 void CSingleton::cleanInstance()
37 {
38     delete m_pSingleton; m_pSingleton = NULL;
39 }
40  
41 int CSingleton::getValue()
42 {
43     return m_iValue;
44 }
45  
46 void CSingleton::setValue(int iValue)
47 {
48     m_iValue = iValue;
49 }
50  
51 int main()
52 {
53     CSingleton* pSingleton1 = CSingleton::getInstance();
54     CSingleton* pSingleton2 = CSingleton::getInstance();
55     pSingleton1->setValue(123);
56     if (pSingleton1->getValue() == pSingleton2->getValue())
57     {
58         cout << "Two objects is the same instance" << endl;
59     }
60     else
61     {
62         cout << "Two objects isn't the same instance" << endl;
63     }
64  
65     CSingleton::cleanInstance();
66     return 0;
67 }
哈哈,看清楚了吗?就是在进程运行的时候就对这个单件进行实例化,可是这样似乎又不能达到延迟实例化的目的啦。如果我们的对象对资源占用非常大,而我们的进行在整个过程中其实并没有用到这个单件,那岂不是白白浪费资源了嘛。还有更好的办法。
实现3:
 1 #include <iostream>
 2 using namespace std;
 3  
 4 class CSingleton
 5 {
 6 public:
 7     static CSingleton* getInstance();
 8     int getValue();
 9     void setValue(int iValue);
10 private:
11     int m_iValue;
12     CSingleton();
13     ~CSingleton();
14 };
15  
16 CSingleton::CSingleton()
17 {
18     cout << "Constructor" << endl;
19 }
20  
21 CSingleton::~CSingleton()
22 {
23     cout << "Destructor" << endl;
24 }
25  
26 CSingleton* CSingleton::getInstance()
27 {
28     static CSingleton single;
29     return &single;
30 }
31  
32 int CSingleton::getValue()
33 {
34     return m_iValue;
35 }
36  
37 void CSingleton::setValue(int iValue)
38 {
39     m_iValue = iValue;
40 }
41  
42 int main()
43 {
44     cout << "Process begin" << endl;
45     CSingleton* pSingleton1 = CSingleton::getInstance();
46     CSingleton* pSingleton2 = CSingleton::getInstance();
47     pSingleton1->setValue(123);
48     if (pSingleton1->getValue() == pSingleton2->getValue())
49     {
50         cout << "Two objects is the same instance" << endl;
51     }
52     else
53     {
54         cout << "Two objects isn't the same instance" << endl;
55     }
56     return 0;
57 }
看下运行结果吧:

Process begin
Constructor
Two objects is the same instance
Destructor

是不是跟预想的一样呢?把单件声明为成员函数中的静态成员,这样既可以达到延迟实例化的目的,又能达到线程安全的目的,而且看结果的最后,是不是在程序退出的时候,还自动的调用了析构函数呢?这样我们就可以把资源的释放放到析构函数里边,等到程序退出的时候,进程会自动释放这些静态成员的。

原文地址:https://www.cnblogs.com/berlin-sun/p/CSingleton.html