单例模式

  1. 最简单的单例模式
 1 //singelton.h文件
 2 class CSingelton
 3 {
 4 public:
 5     static CSingelton* getSingelton();
 7 private:
 8     CSingelton();
 9     CSingelton(const CSingelton& other) = delete;
10     CSingelton& operator=(const CSingelton& other) = delete;
11 };
 1 //singelton.cpp
 2 CSingelton* CSingelton::getSingelton()
 3 {
 4     //线程安全
 5     static CSingelton singleton;
 6     return &singleton;
 7 }
 8 
 9 CSingelton::CSingelton()
10 {
11 
12 }

  期望用户通过getSingelton()来访问CSingelton的唯一实例, 但是用户可以将获得的指针付给其他变量,难以达到只能通过getSingelton() 来访问的目的。改进如下

  2.只能通过getSingelton() 来访问简单单例

 1 //singelton.h
 2 class CSingelton
 3 {
 4 public:
 5     static CSingelton& getSingelton();
 6 
 7 private:
 8     CSingelton();
 9     CSingelton(const CSingelton& other) = delete;
10     CSingelton& operator=(const CSingelton& other) = delete;
11 };
 1 //singelton.cpp
 2 CSingelton& CSingelton::getSingelton()
 3 {
 4     //线程安全
 5     static CSingelton singleton;
 6     return singleton;
 7 }
 8 
 9 CSingelton::CSingelton()
10 {
11 
12 }

达到了用户只能通过getSingelton()来访问CSingelton的唯一实例的目的。但如果这个唯一实例需要在堆上分配内存,1、2就不适用了。

  3.在堆上分配的单例(饿汉模式)

 1 //singelton.h
 2 class CSingelton
 3 {
 4 public:
 5     static CSingelton* getSingelton();
 6 
 7 private:
 8     CSingelton();
 9     CSingelton(const CSingelton& other) = delete;
10     CSingelton& operator=(const CSingelton& other) = delete;
11         static CSingelton*  m_pSingelton;
12 };    

 

 1 //singelton.cpp
 2 
 3 CSingelton* CSingelton::m_pSingelton = new CSingelton;
 4 CSingelton* CSingelton::getSingelton()
 5 {
 6     return m_pSingelton ;
 7 }
 8 CSingelton::CSingelton()
 9 {
10 
11 }

  第一次访问实例前,单例已创建好,所以俗称饿汉模式。缺点是存在1)内存泄漏

 

   4.在堆上分配的单例(懒汉模式)

 1 //singelton.h
 2 class CSingelton
 3 {
 4 public:
 5     static CSingelton* getSingelton();
 6 
 7 private:
 8     CSingelton();
 9     CSingelton(const CSingelton& other) = delete;
10     CSingelton& operator=(const CSingelton& other) = delete;
11     static     CSingelton*    m_pSingleton;
12 
13 };
 1 CSingelton* CSingelton::m_pSingleton = nullptr;
 2 CSingelton* CSingelton::getSingelton()
 3 {
 4     if (nullptr == m_pSingleton)
 5     {
 6         m_pSingleton = new CSingelton
 7     }
 8     return m_pSingleton;
 9 }
10 
11 CSingelton::CSingelton()
12 {
13 
14 }

由于第一次获取对象时才创建,所以俗称为懒汉模式。

缺点:1)此单例会造成内存泄漏,如何释放?2)单例构造不是线程安全的

5.线程安全懒汉模式单例

 1 //safeSingelton.h
 2 
 3 #include <mutex>
 4 class CSafeSingelton
 5 {
 6 public:
 7     static CSafeSingelton* getSingelton();
 8 
 9 private:
10     CSafeSingelton();
11     CSafeSingelton(const CSafeSingelton& other) = delete;
12     CSafeSingelton& operator=(const CSafeSingelton& other) = delete;
13     static     CSafeSingelton*    m_pSingleton;
14     static    std::mutex    m_mtx;
15 
16 };
 1 //safeSingelton.cpp
 2 
 3 CSafeSingelton*    CSafeSingelton::m_pSingleton = nullptr;
 4 CSafeSingelton* CSafeSingelton::getSingelton()
 5 {
 6     if (nullptr == m_pSingleton)
 7     {
 8         std::lock_guard<std::mutex> lock(m_mtx);
 9         //此处第二次非空判断是必要的,因为第一次非空判断获取锁之后,其他线程可能已经将单例对像实例化出来了
10         if (nullptr == m_pSingleton)
11         {
12             m_pSingleton = new CSafeSingelton;
13         }
14     }
15     return m_pSingleton;
16 }
17 
18 CSafeSingelton::CSafeSingelton()
19 {
20 
21 }

   此方式的缺点1)内存泄漏 2)将单例指针暴露在外

 

posted @ 2020-02-18 15:03  peterliang  阅读(145)  评论(0编辑  收藏  举报