单例模式

打印 上一主题 下一主题

主题 938|帖子 938|积分 2818

饿汉

饿汉式(Eager Initialization)是一种简单的单例模式实现方法,在类加载时就创建唯一实例。
  1. class Singleton {
  2. private:
  3.     // 将构造函数、拷贝构造函数和赋值运算符设为私有,防止外部实例化和复制
  4.     Singleton() {}
  5.     Singleton(const Singleton&) = delete;
  6.     Singleton& operator=(const Singleton&) = delete;
  7.    
  8. public:
  9.     static Singleton& getInstance() {
  10.         static Singleton instance;  // 在静态函数中创建唯一实例
  11.         return instance;
  12.     }
  13. };
复制代码
Singleton类中的构造函数、拷贝构造函数和赋值运算符被私有化,并且利用了delete关键字,这样可以防止外部直接实例化对象或举行拷贝。而getInstance()方法是静态方法,它返回一个指向唯一实例的引用。
在getInstance()方法中,我们利用了局部静态变量instance来保存唯一的实例。由于局部静态变量的特性,它只会在初次调用getInstance()方法时创建,之后的调用都会直接返回该实例。这样可以或许保证在程序启动时就创建了单例对象。
通过调用Singleton::getInstance()就可以获取到全局唯一的Singleton实例。
说明:


  • 饿汉式的特点是在类加载的时候就创建实例,所以称为"饿汉式",因为它比较"急切"地去创建实例。
  • 饿汉式的实现通过一个静态变量instance来持有唯一实例,因为静态变量在程序启动时就会初始化。
  • 由于在程序启动时就创建实例,所以不存在多线程并发访问创建实例的问题,这种方式是线程安全的。
  • 饿汉式的缺点是无法实现延迟加载,纵然在某些环境下没有利用到该单例对象,它仍然会被创建和占用内存。
别的,由于静态变量的生命周期与程序的生命周期相同,如果应用程序中从未利用过该单例对象,那么它可能会浪费一些内存资源。
饿汉式是一种简单但不够灵活的单例模式实现方法。它适用于单例对象的创建成本较低的场景。
懒汉

C++中的懒汉式(Lazy Initialization)是一种延迟加载的单例模式实现方式。它只有在必要利用单例对象时才举行创建,而不是在类加载时就创建实例。
  1. class Singleton {
  2. private:
  3.     // 私有的静态成员指针,用于存储单例对象
  4.     static Singleton* instance;
  5.     // 将构造函数、拷贝构造函数和赋值运算符私有化,防止外部实例化和复制
  6.     Singleton() {}
  7.     Singleton(const Singleton& other) {}
  8.     Singleton& operator=(const Singleton& other) {}
  9. public:
  10.     // 静态成员函数,用于获取单例对象的引用
  11.     static Singleton* getInstance() {
  12.         if (instance == nullptr) {
  13.             instance = new Singleton();
  14.         }
  15.         return instance;
  16.     }
  17. };
  18. // 初始化静态成员变量为nullptr
  19. Singleton* Singleton::instance = nullptr;
复制代码
Singleton类具有一个私有的静态成员指针instance,并通过调用静态成员函数getInstance()返回单例对象的引用。在初次调用getInstance()时,会检查instance是否为null,如果是,则创建一个新的Singleton对象并赋值给instance,否则直接返回现有的instance。
懒汉式单例模式延迟了对象的创建时间,当第一次利用单例对象时才举行实例化。这种延迟加载的方式可以节省资源并满足按需创建的需求。但是必要注意的是,在多线程环境下,懒汉式单例模式可能会引发线程安全问题,因为多个线程可能同时访问到getInstance()方法,从而导致创建多个实例。为了办理这个问题,可以利用线程安全的技术(如加锁)来保证只创建一个实例。
C++懒汉式(Lazy Initialization)在多线程环境下可能存在线程安全性问题。当多个线程同时调用实例获取方法时,可能会导致创建多个实例,违反了单例模式的初志。
以下是两种常见的办理方案:

  • 加锁:利用互斥锁(mutex)来保证在实例创建过程中只有一个线程可以或许进入关键代码段,其他线程必要等待。在懒汉式实例获取方法中加入互斥锁可以办理线程安全性问题。
    1. class Singleton {
    2. private:
    3.     static Singleton* instance;
    4.     static std::mutex mutex;
    5.     Singleton() {}
    6.     Singleton(const Singleton& other) {}
    7.     Singleton& operator=(const Singleton& other) {}
    8. public:
    9.     static Singleton* getInstance() {
    10.         std::lock_guard<std::mutex> lock(mutex);  // 加锁
    11.         if (instance == nullptr) {
    12.             instance = new Singleton();
    13.         }
    14.         return instance;
    15.     }
    16. };
    17. Singleton* Singleton::instance = nullptr;
    18. std::mutex Singleton::mutex;
    复制代码
  • 双重检查锁定(Double-Checked Locking):双重检查锁定是一种优化的加锁方式,在加锁前后都举行了判断,镌汰了不必要的锁开销。
  1. class Singleton {
  2. private:
  3.     static Singleton* instance;
  4.     static std::mutex mutex;
  5.     Singleton() {}
  6.     Singleton(const Singleton& other) {}
  7.     Singleton& operator=(const Singleton& other) {}
  8. public:
  9.     static Singleton* getInstance() {
  10.         if (instance == nullptr) {  // 第一次检查
  11.             std::lock_guard<std::mutex> lock(mutex);  // 加锁
  12.             if (instance == nullptr) {  // 第二次检查
  13.                 instance = new Singleton();  // 创建实例
  14.             }
  15.         }
  16.         return instance;
  17.     }
  18. };
  19. Singleton* Singleton::instance = nullptr;
  20. std::mutex Singleton::mutex;
复制代码
局部静态变量(Local static variable)

C++中,利用局部静态变量实现单例模式是一种常见且简便的方式。局部静态变量指的是在函数内部界说的静态变量,这种变量在程序实行过程中只会被初始化一次。

  1. class Singleton {
  2. private:
  3.     Singleton() {}
  4.     Singleton(const Singleton& other) = delete;
  5.     Singleton& operator=(const Singleton& other) = delete;
  6. public:
  7.     static Singleton& getInstance() {
  8.         static Singleton instance;
  9.         return instance;
  10.     }
  11. };
复制代码
利用了 C++11 标准的静态局部变量初始化的线程安全性子。C++11 规定对于静态局部变量的初始化是线程安全的,并且只会在第一次调用该函数时举行初始化。因此,无需额外的线程同步措施,可以或许确保只有一个实例被创建。
当调用 getInstance() 方法时,静态局部变量 instance 会被初始化,并返回该实例的引用。由于静态局部变量的生命周期在程序运行期间连续存在,所以每次调用 getInstance() 方法都会返回同一个实例。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

王國慶

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表