《C++ 单例模式》
在 C++ 中,单例模式(Singleton Pattern) 是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问该实例。单例模式常用于管理全局资源、配置或共享状态,避免重复创建对象带来的开销或冲突。
1. 单例模式的核心思想
(1) 核心特性
- 唯一实例:整个程序中只能有一个该类的对象。
- 全局访问:通过静态方法(如
getInstance())获取唯一实例。 - 延迟初始化(Lazy Initialization):实例在第一次使用时才创建(可选)。
- 禁止拷贝和赋值:防止通过拷贝或赋值创建新实例。
(2) 适用场景
- 全局配置管理(如
MediaConfig、日志系统)。 - 共享资源访问(如数据库连接池、线程池)。
- 硬件设备控制(如打印机、传感器)。
- 缓存系统(避免重复计算或加载数据)。
2. 单例模式的 C++ 实现
(1) 经典实现(C++98/03 风格)
#include <mutex> class Singleton { private: static Singleton* instance; // 静态成员变量存储唯一实例 static std::mutex mtx; // 互斥锁(线程安全) // 私有构造函数,防止外部 new Singleton() {} // 禁止拷贝构造和赋值 Singleton(const Singleton&) = delete; Singleton& operator=(const Singleton&) = delete; public: // 获取唯一实例(线程安全) static Singleton* getInstance() { if (instance == nullptr) { // 双重检查锁定(DCLP) std::lock_guard<std::mutex> lock(mtx); if (instance == nullptr) { instance = new Singleton(); } } return instance; } // 其他业务方法... void doSomething() { // ... } }; // 初始化静态成员 Singleton* Singleton::instance = nullptr; std::mutex Singleton::mtx;
问题:
- 内存泄漏:
new Singleton()未释放,需手动管理。 - 双重检查锁定(DCLP) 在 C++98/03 中可能因指令重排序导致问题(C++11 后修复)。
(2) C++11 推荐实现(线程安全 + 无内存泄漏)
方法 1:局部静态变量(Meyer's Singleton)
class Singleton { private: Singleton() {} // 私有构造函数 // 禁止拷贝构造和赋值 Singleton(const Singleton&) = delete; Singleton& operator=(const Singleton&) = delete; public: // 获取唯一实例(C++11 保证线程安全)
static Singleton& getInstance() { static Singleton instance; // 局部静态变量,线程安全 return instance; } void doSomething() { // ... } };
优点:
- 线程安全:C++11 保证局部静态变量的初始化是线程安全的。
- 懒加载:实例在第一次调用
getInstance()时创建。 - 无内存泄漏:程序退出时自动销毁静态变量。
方法 2:智能指针(std::unique_ptr)
#include <memory> #include <mutex> class Singleton { private: static std::unique_ptr<Singleton> instance; static std::mutex mtx; Singleton() {} Singleton(const Singleton&) = delete; Singleton& operator=(const Singleton&) = delete; public: static Singleton* getInstance() { if (!instance) { std::lock_guard<std::mutex> lock(mtx); if (!instance) { instance = std::make_unique<Singleton>(); } } return instance.get(); } }; // 初始化静态成员 std::unique_ptr<Singleton> Singleton::instance = nullptr; std::mutex Singleton::mtx;
适用场景:
- 需要显式控制实例生命周期(如提前销毁)。
3. 单例模式的优缺点
(1) 优点
控制实例数量 确保全局唯一,避免资源浪费 线程安全 C++11 后局部静态变量实现简单且安全 延迟初始化 按需创建,节省启动时间 封装性好 比全局变量更安全,可控制访问权限
(2) 缺点
难以测试 单例的静态依赖可能导致单元测试困难 滥用风险 过度使用单例可能导致代码耦合度高 内存泄漏风险 经典实现需手动释放内存(C++11 局部静态变量无此问题) 多线程问题 C++98/03 的双重检查锁定可能有隐患
demo:
class Logger { private: Logger() {} // 私有构造函数 public: static Logger& getInstance() { static Logger logger; // 线程安全 + 懒加载 return logger; } void log(const std::string& message) { // 记录日志... } }; // 使用 Logger::getInstance().log("Hello, Singleton!");
浙公网安备 33010602011771号