在 C++ 中,单例模式(Singleton Pattern) 是一种创建型设计模式,其核心目标是确保一个类只有一个实例,并提供一个全局访问点。它常用于管理全局唯一的资源(如配置、日志系统、线程池等)。以下是单例模式的详细实现和分析:
new
创建实例。最简单的单例实现,但存在多线程安全问题:
class Singleton {
private:
static Singleton* instance; // 静态成员保存唯一实例
Singleton() {} // 私有构造函数
Singleton(const Singleton&) = delete; // 禁用拷贝构造
Singleton& operator=(const Singleton&) = delete; // 禁用赋值操作符
public:
static Singleton* getInstance() {
if (instance == nullptr) {
instance = new Singleton();
}
return instance;
}
};
// 初始化静态成员
Singleton* Singleton::instance = nullptr;
getInstance()
,可能创建多个实例。通过双重检查锁定(Double-Checked Locking) 优化性能和线程安全:
#include <mutex>
class Singleton {
private:
static Singleton* instance;
static std::mutex mtx; // 互斥锁
Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
static Singleton* getInstance() {
if (instance == nullptr) { // 第一次检查(避免每次加锁)
std::lock_guard<std::mutex> lock(mtx);
if (instance == nullptr) { // 第二次检查(确保线程安全)
instance = new Singleton();
}
}
return instance;
}
};
// 初始化静态成员
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;
在程序启动时(静态初始化阶段)直接创建实例,天然线程安全:
class Singleton {
private:
static Singleton* instance;
Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
static Singleton* getInstance() {
return instance;
}
};
// 在类外部直接初始化实例
Singleton* Singleton::instance = new Singleton();
利用局部静态变量的特性,C++11 保证其初始化是线程安全的:
class Singleton {
private:
Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
static Singleton& getInstance() {
static Singleton instance; // C++11 保证线程安全的局部静态初始化
return instance;
}
};
delete
)。若单例实例需要显式释放资源,可以添加销毁方法:
class Singleton {
private:
Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
static void destroyInstance() {
if (instance != nullptr) {
delete instance;
instance = nullptr;
}
}
};
优点 | 缺点 |
---|---|
全局唯一访问点,方便资源管理 | 隐藏依赖关系,增加代码耦合性 |
节省内存和资源 | 难以扩展(如需要多个实例时需重构) |
延迟初始化(懒汉式) | 多线程环境下需处理同步问题 |
单元测试困难(全局状态难以隔离或模拟) |
#include <iostream>
class Logger {
private:
Logger() {} // 私有构造函数
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;
public:
static Logger& getInstance() {
static Logger instance;
return instance;
}
void log(const std::string& message) {
std::cout << "Log: " << message << std::endl;
}
};
int main() {
Logger::getInstance().log("Application started");
Logger::getInstance().log("Processing data...");
return 0;
}
Log: Application started
Log: Processing data...
以下是一个完整的单例模式实现,包含实例的显式销毁方法,并通过双重检查锁定确保线程安全:
#include <iostream>
#include <mutex>
class Singleton {
private:
static Singleton* instance; // 静态单例实例指针
static std::mutex mtx; // 互斥锁(用于线程安全)
// 私有化构造函数和析构函数
Singleton() {
std::cout << "Singleton instance created." << std::endl;
}
~Singleton() {
std::cout << "Singleton instance destroyed." << std::endl;
}
// 禁用拷贝和赋值
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
// 获取单例实例(线程安全)
static Singleton* getInstance() {
if (instance == nullptr) { // 第一次检查(避免每次加锁)
std::lock_guard<std::mutex> lock(mtx);
if (instance == nullptr) { // 第二次检查(确保线程安全)
instance = new Singleton();
}
}
return instance;
}
// 显式销毁单例实例(线程安全)
static void destroyInstance() {
std::lock_guard<std::mutex> lock(mtx); // 加锁保护
if (instance != nullptr) {
delete instance;
instance = nullptr; // 重置指针,避免悬空引用
}
}
// 示例方法
void doSomething() {
std::cout << "Doing something..." << std::endl;
}
};
// 静态成员初始化
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;
// 使用示例
int main() {
// 获取单例实例并操作
Singleton* s1 = Singleton::getInstance();
s1->doSomething();
// 显式销毁实例
Singleton::destroyInstance();
// 再次获取实例(会创建新实例)
Singleton* s2 = Singleton::getInstance();
s2->doSomething();
return 0;
}
Singleton instance created.
Doing something...
Singleton instance destroyed.
Singleton instance created.
Doing something...
std::mutex
和 std::lock_guard
确保 getInstance()
和 destroyInstance()
的线程安全。destroyInstance()
方法通过 delete
释放实例内存,并将 instance
指针置为 nullptr
。getInstance()
会创建新实例(根据需求可修改为禁止重新创建)。~Singleton()
可以释放单例持有的资源(如文件句柄、网络连接)。destroyInstance()
,单例实例将在程序结束时由操作系统回收(可能不符合预期)。若需禁止销毁后重新创建实例,可增加一个标志位:
class Singleton {
private:
static bool destroyed; // 新增销毁标志
public:
static Singleton* getInstance() {
if (destroyed) {
throw std::runtime_error("Singleton instance has been destroyed.");
}
// ...(原有逻辑)
}
static void destroyInstance() {
// ...(原有逻辑)
destroyed = true; // 标记已销毁
}
};
// 初始化静态成员
bool Singleton::destroyed = false;
单例模式在 C++ 中通过控制实例化过程确保全局唯一性。现代 C++ 推荐使用 局部静态变量 实现(Meyers’ Singleton),既简洁又线程安全。需根据实际需求权衡懒汉式与饿汉式,并注意避免滥用单例导致代码耦合性增加。