单例模式【C++设计模式】
- IT业界
- 2025-08-25 06:51:01

文章目录 单例模式饿汉模式懒汉模式 单例场景 单例模式 饿汉模式 将构造函数设置为私有,并将拷贝构造函数和赋值运算符重载函数设置为私有或删除,防止外部创建或拷贝对象。提供一个指向单例对象的static指针,并在程序入口之前完成单例对象的初始化。提供一个全局访问点获取单例对象 class Singleton { public: //3、提供一个全局访问点获取单例对象 static Singleton* GetInstance() { return _inst; } private: //1、将构造函数设置为私有,并防拷贝 Singleton() {} Singleton(const Singleton&) = delete; Singleton& operator=(const Singleton&) = delete; //2、提供一个指向单例对象的static指针 static Singleton* _inst; }; //在程序入口之前完成单例对象的初始化 Singleton* Singleton::_inst = new Singleton;
线程安全相关问题:
饿汉模式在程序运行主函数之前就完成了单例对象的创建,由于main函数之前是不存在多线程的,因此饿汉模式下单例对象的创建过程是线程安全的
后续所有多线程要访问这个单例对象,都需要通过调用GetInstance函数来获取,这个获取过程是不需要加锁的,因为这是一个读操作
当然,如果线程通过GetInstance获取到单例对象后,要用这个单例对象进行一些线程不安全的操作,那么这时就需要加锁了
例如:
#include<map> #include<string> #include<iostream> using namespace std; class Singleton { public: //提供获取单例对象的接口函数 static Singleton& GetInstance() { return _sinst; } void func(); void Add(const pair<string, string>& kv) { _dict[kv.first] = kv.second; } void Print() { for (auto& e : _dict) { cout << e.first << ":" << e.second << endl; } cout << endl; } private: // 1、构造函数私有 Singleton() { // ... } // 3、防拷贝 Singleton(const Singleton& s) = delete; Singleton& operator=(const Singleton& s) = delete; map<string, string> _dict; // 静态实例 static Singleton _sinst; }; Singleton Singleton::_sinst; int main() { //Singleton::GetInstance(); cout << &Singleton::GetInstance() << endl; cout << &Singleton::GetInstance() << endl; cout << &Singleton::GetInstance() << endl; // Singleton copy(Singleton::GetInstance()); Singleton::GetInstance().Add({ "xxx", "111" }); Singleton::GetInstance().Add({ "yyy", "222" }); Singleton::GetInstance().Add({ "zzzzz", "333" }); Singleton::GetInstance().Add({ "abc", "333" }); Singleton::GetInstance().Print(); } 懒汉模式 将构造函数设置为私有,并将拷贝构造函数和赋值运算符重载函数设置为私有或删除,防止外部创建或拷贝对象。提供一个指向单例对象的static指针,并在程序入口之前先将其初始化为空。提供一个全局访问点获取单例对象 class Singleton { public: //3、提供一个全局访问点获取单例对象 static Singleton* GetInstance() { //双检查 if (_inst == nullptr) { _mtx.lock(); if (_inst == nullptr) { _inst = new Singleton; } _mtx.unlock(); } return _inst; } private: //1、将构造函数设置为私有,并防拷贝 Singleton() {} Singleton(const Singleton&) = delete; Singleton& operator=(const Singleton&) = delete; //2、提供一个指向单例对象的static指针 static Singleton* _inst; static mutex _mtx; //互斥锁 }; //在程序入口之前先将static指针初始化为空 Singleton* Singleton::_inst = nullptr; mutex Singleton::_mtx; //初始化互斥锁饿汉模式的优点就是简单,但是它的缺点也比较明显。饿汉模式在程序运行主函数之前就会创建单例对象,如果单例类的构造函数中所做的工作比较多,就会导致程序迟迟无法进入主函数,在外部看来就好像是程序卡住了。
此外,如果有多个单例类需要创建单例对象,并且它们之间的初始化存在某种依赖关系,比如单例对象A的创建必须在单例对象B之后,此时饿汉模式也会存在问题,因为我们无法保证这多个单例对象中的哪个对象先创建
而懒汉模式就能很好的解决上述饿汉模式的缺点,因为懒汉模式并不是一开始就完成单例对象的创建,因此不会导致程序迟迟无法进入主函数,并且懒汉模式中各个单例对象创建的顺序是由各个单例类中的GetInstance函数第一次被调用的顺序决定,因此是可控制的。 懒汉模式的缺点就是,在编码上比饿汉模式复杂,在创建单例对象时需要考虑线程安全的问题
单例场景在 RPC(Remote Procedure Call,远程过程调用)项目中,单例模式是一种常见的设计模式,用于确保某个类只有一个实例,并提供一个全局访问点。单例模式在 RPC 项目中特别有用,例如用于管理配置、日志记录器或连接池等资源。
例如:在 RPC 项目中使用单例模式来管理一个全局的配置对象
#include <iostream> #include <mutex> #include <memory> class ConfigManager { private: // 静态指针,存储唯一的实例 static std::unique_ptr<ConfigManager> instance; // 私有化构造函数,防止外部直接构造 ConfigManager() { std::cout << "ConfigManager initialized." << std::endl; } // 禁止拷贝构造和赋值操作 ConfigManager(const ConfigManager&) = delete; ConfigManager& operator=(const ConfigManager&) = delete; public: // 提供一个静态方法获取实例 static ConfigManager& getInstance() { static std::once_flag onceFlag; std::call_once(onceFlag, []() { instance = std::make_unique<ConfigManager>(); }); return *instance; } // 示例方法:获取配置值 std::string getConfigValue(const std::string& key) { // 这里可以实现从配置文件或数据库中读取配置 return "value_for_" + key; } }; // 初始化静态成员变量 std::unique_ptr<ConfigManager> ConfigManager::instance = nullptr;使用单例
#include <iostream> int main() { // 获取单例实例 ConfigManager& configManager = ConfigManager::getInstance(); // 使用单例实例 std::string value = configManager.getConfigValue("database_url"); std::cout << "Config Value: " << value << std::endl; return 0; }代码理解:
私有化构造函数: ConfigManager():构造函数被私有化,防止外部直接构造对象。禁止拷贝构造和赋值操作,确保类的实例唯一性。 静态实例: static std::unique_ptr<ConfigManager> instance;:静态成员变量,存储唯一的实例。使用 std::unique_ptr 确保实例在程序结束时自动释放。 全局访问点: static ConfigManager& getInstance():提供一个静态方法,用于获取唯一的实例。使用 std::call_once 和 std::once_flag 确保实例只被初始化一次,即使在多线程环境下也能安全工作。 延迟初始化: 实例仅在第一次调用 getInstance() 时初始化,避免不必要的资源占用。单例模式【C++设计模式】由讯客互联IT业界栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“单例模式【C++设计模式】”
上一篇
分巧克力(二分查找)