怎样实现单例模式?

[复制链接]
发表于 2025-12-1 14:46:04 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
概念

单例模式(Singleton Pattern)是一种筹划模式,确保一个类只有一个实例,并提供一个全局访问点。它常用于必要控制资源访问的场景,如数据库毗连、日志日志纪录大概设置管理等。
方式

懒汉式单例

懒汉式单例是在第一次被哀求时创建实例。为了确保线程安全,通常使用 std::mutex 举行掩护。
  1. #include <iostream>  
  2. #include <mutex>  
  3. class Singleton {  
  4. public:  
  5.     // 禁止拷贝构造和赋值  
  6.     Singleton(const Singleton&) = delete;  
  7.     Singleton& operator=(const Singleton&) = delete;  
  8.     static Singleton& getInstance() {  
  9.         static Singleton instance; // 此时实例在第一次调用时创建  
  10.         return instance;  
  11.     }  
  12.     void someMethod() {  
  13.         std::cout << "Doing something in Singleton." << std::endl;  
  14.     }  
  15. private:  
  16.     Singleton() {  
  17.         std::cout << "Singleton Constructor" << std::endl; // 建构函数  
  18.     }  
  19.    
  20.     ~Singleton() {  
  21.         std::cout << "Singleton Destructor" << std::endl; // 析构函数  
  22.     }  
  23. };  
  24. int main() {  
  25.     Singleton::getInstance().someMethod(); // 访问单例  
  26.     return 0;  
  27. }
复制代码
代码分析

  • 私有构造函数:确保外部不能直接创建实例。
  • 克制拷贝:复制构造函数和赋值运算符被删除,以防止复制。
  • 静态局部变量:在静态方法 getInstance 中声明一个静态局部变量,这个变量 在第一次使用时初始化,后续调用将返回雷同的实例。
  • 线程安全:C++11 及以上版本中,局部静态变量在多线程中是安全的,不必要额外的锁。
饿汉式单例

饿汉式单例在步调启动时就创建实例,岂论是否被使用。如许可以制止多线程中的同步题目,但在资源使用上大概会浪费。
  1. #include <iostream>  
  2. class Singleton {  
  3. public:  
  4.     // 禁止拷贝构造和赋值  
  5.     Singleton(const Singleton&) = delete;  
  6.     Singleton& operator=(const Singleton&) = delete;  
  7.     static Singleton& getInstance() {  
  8.         return instance; // 直接返回实例  
  9.     }  
  10.     void someMethod() {  
  11.         std::cout << "Doing something in Singleton." << std::endl;  
  12.     }  
  13. private:  
  14.     Singleton() {  
  15.         std::cout << "Singleton Constructor" << std::endl; // 建构函数  
  16.     }  
  17.     ~Singleton() {  
  18.         std::cout << "Singleton Destructor" << std::endl; // 析构函数  
  19.     }  
  20.     static Singleton instance; // 静态实例  
  21. };  
  22. // 定义静态成员  
  23. Singleton Singleton::instance;  
  24. int main() {  
  25.     Singleton::getInstance().someMethod(); // 访问单例  
  26.     return 0;  
  27. }
复制代码
代码分析

  • 静态实例:在类的内部声明一个静态成员 instance,在类外界说该成员。
  • 构造函数:与懒汉式雷同,构造函数和析构函数是私有的,以防止外部实例化。
线程安全的懒汉式单例(使用锁)

这种方法在创建单例实例时使用互斥锁来实现控制,确保多个线程差异时创建。
  1. #include <iostream>  
  2. #include <mutex>  
  3. class Singleton {  
  4. public:  
  5.     static Singleton* getInstance() {  
  6.         std::lock_guard<std::mutex> lock(mu); // 加锁  
  7.         if (!instance)  
  8.             instance = new Singleton(); // 延迟加载  
  9.         return instance;  
  10.     }  
  11.     void someMethod() {  
  12.         std::cout << "Doing something in Singleton." << std::endl;  
  13.     }  
  14. private:  
  15.     Singleton() = default; // 私有构造函数  
  16.     ~Singleton() = default; // 私有析构函数  
  17.     Singleton(const Singleton&) = delete; // 禁止拷贝构造  
  18.     Singleton& operator=(const Singleton&) = delete; // 禁止赋值  
  19.     static Singleton* instance; // 静态实例指针  
  20.     static std::mutex mu; // 互斥量  
  21. };  
  22. // 定义静态成员  
  23. Singleton* Singleton::instance = nullptr;  
  24. std::mutex Singleton::mu;  
  25. int main() {  
  26.     Singleton::getInstance()->someMethod(); // 访问单例  
  27.     return 0;  
  28. }
复制代码
代码分析

  • 互斥量:使用 std::mutex 控制访问,以实现线程安全。每当访问 getInstance 时,lock_guard 主动加锁。
  • 动态分配:实例在初次访问时通过 new 创建,依靠用户在得当的位置调用 delete 烧毁对象。
接纳 std::call_once

C++11 中引入的 std::call_once 可以确保线程安全的单例实现。
  1. #include <iostream>  
  2. #include <mutex>  
  3. class Singleton {  
  4. public:  
  5.     static Singleton& getInstance() {  
  6.         std::call_once(initInstanceFlag, &Singleton::initSingleton);  
  7.         return *instance;  
  8.     }  
  9.     void someMethod() {  
  10.         std::cout << "Doing something in Singleton." << std::endl;  
  11.     }  
  12. private:  
  13.     Singleton() {  
  14.         std::cout << "Singleton Constructor" << std::endl;  
  15.     }  
  16.    
  17.     ~Singleton() {  
  18.         std::cout << "Singleton Destructor" << std::endl;  
  19.     }  
  20.     static void initSingleton() {  
  21.         instance = new Singleton();  
  22.     }  
  23.     static Singleton* instance;  
  24.     static std::once_flag initInstanceFlag; // 初始化标志  
  25. };  
  26. // 静态成员初始化  
  27. Singleton* Singleton::instance = nullptr;  
  28. std::once_flag Singleton::initInstanceFlag;  
  29. int main() {  
  30.     Singleton::getInstance().someMethod();  
  31.     return 0;  
  32. }
复制代码
代码分析

  • std:nce_flag:用于包管指定的函数只被调用一次。
  • std::call_once:确保在多线程情况下只会初始化一次实例。
总结

单例模式可以通过多种方式实现,包罗懒汉式、饿汉式、线程安全的懒汉式、使用 std::call_once 等。选择符合的实现方式紧张取决于项目标需求、线程安全需求以及怎样管理生命周期等因素。对于大多数情况,使用 C++11 提供的懒汉式联合 std::call_once 是最保举的做法,由于它既包管了线程安全,又轻巧易懂。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表