【C++设计模式】(三)创建型模式:单例模式

文章目录

(三)创建型模式:单例模式

单例模式在于确保一个类只有一个实例,并提供一个全局访问点来访问该实例。在某些情况下,某些代码组件(如线程池,日志记录器)需要在整个应用程序中共享,使用单例模式可以实现组件资源的复用,并简化系统设计。

单例模式实现方式主要包括饿汉式和懒汉式两种。

饿汉式

饿汉式是指在类加载的时候就创建单例实例,不管后续是否会使用这个实例。

cpp 复制代码
class Singleton {
private:
    static Singleton* instance; // 静态成员变量,属于类本身而不是类的任何特定对象
    
    Singleton() {}              // 私有构造函数防止外部实例化

public:
    static Singleton* getInstance() {  // 全局访问点
        return instance;
    }
};

Singleton* Singleton::instance = new Singleton();  // 在静态成员变量初始化时创建实例

在多线程环境下,饿汉式是线程安全的,因为实例在类加载时就已经创建好了,不存在并发访问创建实例的问题。

示例:

cpp 复制代码
#include <iostream>  
  
class Singleton {  
private:  
    static Singleton instance; // 静态实例,在类加载时构造  
    Singleton() {} // 私有构造函数  
  
public:  
    static Singleton& getInstance() {  
        return instance;  
    }  
  
    void doSomething() {  
        std::cout << "Doing something..." << std::endl;  
    }  
};  
  
Singleton Singleton::instance; // 静态实例初始化  
  
int main() {  
    Singleton& s1 = Singleton::getInstance();  
    Singleton& s2 = Singleton::getInstance();  
  
    if (&s1 == &s2) {  
        std::cout << "s1 and s2 are the same instance" << std::endl;  
    }  
  
    s1.doSomething();  
    return 0;  
}
复制代码
s1 and s2 are the same instance
Doing something...

懒汉式

懒汉式是指在第一次使用时才会创建单例实例,实例的创建被延迟到第一次使用 getInstance() 方法时。

cpp 复制代码
class Singleton {
private:
    static Singleton* instance;
    
    Singleton() {}  

public:
    static Singleton* getInstance() {
        if (instance == nullptr) { // 第一次使用时才会创建单例实例
            instance = new Singleton();
        }
        return instance;
    }
};

Singleton* Singleton::instance = nullptr;

示例:

cpp 复制代码
#include <iostream>  
  
class Singleton {  
private:  
    static Singleton* instance;  
    Singleton() {} // 私有构造函数  
  
public:  
    static Singleton* getInstance() {  
        if (instance == nullptr) {  
            instance = new Singleton();  
        }  
        return instance;  
    }  
  
    ~Singleton() {  
        delete instance; // 注意:在程序结束时需要确保只调用一次析构函数  
        instance = nullptr;  
    }  
  
    void doSomething() {  
        std::cout << "Doing something..." << std::endl;  
    }  
};  
  
Singleton* Singleton::instance = nullptr; // 静态成员变量初始化  
  
int main() {  
    Singleton* s1 = Singleton::getInstance();  
    Singleton* s2 = Singleton::getInstance();  
  
    if (s1 == s2) {  
        std::cout << "s1 and s2 are the same instance" << std::endl;  
    }  
  
    s1->doSomething();  
    return 0;  
}
复制代码
s1 and s2 are the same instance
Doing something...

懒汉式在多线程环境下是不安全的,因为多个线程可能同时进入判断条件,导致创建多个实例。因此,需要通过加锁等机制来保证线程安全:

cpp 复制代码
 static std::mutex mtx;
 static Singleton* instance;
 
 Singleton* Singleton::getInstance() {
 	// 使用互斥锁(`std::mutex`)来保证只有一个线程能够创建实例。
     std::lock_guard<std::mutex> lock(mtx);
     if (instance == nullptr) {
         instance = new Singleton();
     }
     return instance;
 }

为了避免每次调用都加锁,产生额外的性能开销,可以在加锁的基础上,进行双重检查:

cpp 复制代码
  static std::mutex mtx;
  static Singleton* instance;
  
  Singleton* Singleton::getInstance() {
      if (instance == nullptr) {
          std::lock_guard<std::mutex> lock(mtx);
          if (instance == nullptr) {
              instance = new Singleton();
          }
      }
      return instance;
  }

饿汉式 v.s. 懒汉式

在饿汉式单例模式中,单例的实例在程序启动时就立即创建。这种方式的好处在于它的简单性和线程安全性(无需额外的同步机制)。

在懒汉式单例模式中,单例的实例是在首次被需要时才被创建。这种方式的好处在于它可以延迟实例的创建,从而减少程序启动时的资源消耗和初始化时间。

相关推荐
计算机安禾10 分钟前
【c++面向对象编程】第44篇:typename与class的区别,依赖类型名与template消除歧义
java·jvm·c++
Hua-Jay13 分钟前
OpenCV联合C++/Qt 学习笔记(二十五)----监督学习聚类及K均值聚类
c++·笔记·opencv·学习·计算机视觉·聚类
玖釉-15 分钟前
C++ 中的矩阵介绍:以二维矩阵查找为例
c++·windows·算法·矩阵
乐观的山里娃20 分钟前
【设计模式 13】命令:覆水能收
设计模式
j_xxx404_23 分钟前
Linux线程:从内存分页机制(Page Table/TLB/Page Fault)彻底读懂 Linux 线程本质
linux·运维·服务器·开发语言·c++·人工智能·ai
2301_7890156225 分钟前
C++_string增删查改模拟实现
java·开发语言·c++
学习,学习,在学习30 分钟前
Qt 串口通讯架构
开发语言·c++·qt·架构·qt5
郝学胜-神的一滴39 分钟前
干货版《算法导论》05:从集合接口到排序
开发语言·数据结构·c++·程序人生·算法·排序
Oj92q85H51 小时前
如何在Dev-C++中设置TDM-GCC为默认编译器
java·jvm·c++
汉克老师1 小时前
GESP5级C++考试语法知识(十七、二分算法提高篇(一))
c++·算法·二分算法·gesp5级·gesp五级·二分算法易错点