1.介绍
单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。其核心思想是将类的实例化过程进行严格控制,使得在整个程序运行期间,该类只能创建一个对象实例。这样做的好处是可以避免多个实例带来的资源浪费和数据不一致问题,同时方便对这个唯一实例进行全局访问。它常用于需要全局唯一对象的场景,如配置管理、日志记录、数据库连接池等。
2.单例模式的关键点
1.私有构造函数:防止外部直接实例化。
2.静态实例:类内部维护一个静态实例。
3.全局访问点:通过静态方法提供实例访问。
3.单例模式的实现方式
(1)懒汉式。实例在第一次使用时创建,延迟加载。
class Singleton {
private:
// 私有构造函数
Singleton() {}
// 禁止拷贝构造和赋值操作
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
// 静态实例指针
static Singleton* instance;
public:
// 全局访问点
static Singleton* getInstance() {
if (instance == nullptr) {
instance = new Singleton();
}
return instance;
}
void doSomething() {
// 示例方法
}
};
// 初始化静态成员变量
Singleton* Singleton::instance = nullptr;
问题:非线程安全,多线程环境下可能创建多个实例。
(2)饿汉式。类加载时即创建实例,避免多线程问题。
class Singleton {
private:
// 私有构造函数
Singleton() {}
// 禁止拷贝构造和赋值操作
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
// 静态实例
static Singleton instance;
public:
// 全局访问点
static Singleton* getInstance() {
return &instance;
}
void doSomething() {
// 示例方法
}
};
// 初始化静态成员变量
Singleton Singleton::instance;
(3)双重检查锁。结合懒汉式和同步锁,确保线程安全且高效。
#include <mutex>
class Singleton {
private:
// 私有构造函数
Singleton() {}
// 禁止拷贝构造和赋值操作
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
// 静态实例指针
static Singleton* instance;
static std::mutex mtx;
public:
// 全局访问点
static Singleton* getInstance() {
if (instance == nullptr) {
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;
优点:线程安全且仅在第一次访问时同步。
(4)Meyer's Singleton(静态局部变量)利用C++的静态局部变量特性,实现线程安全的单例模式。
class Singleton {
private:
// 私有构造函数
Singleton() {}
// 禁止拷贝构造和赋值操作
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
// 全局访问点
static Singleton& getInstance() {
static Singleton instance;
return instance;
}
void doSomething() {
// 示例方法
}
};
优点:线程安全(C++11 及以上标准保证静态局部变量的线程安全性)。延迟加载,代码简介。
(5)智能指针单例模式。使用share_ptr或unique_ptr管理单例实例,避免内存泄漏。
#include <memory>
#include <mutex>
class Singleton {
private:
// 私有构造函数
Singleton() {}
// 禁止拷贝构造和赋值操作
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
// 静态智能指针实例
static std::shared_ptr<Singleton> instance;
static std::mutex mtx;
public:
// 全局访问点
static std::shared_ptr<Singleton> getInstance() {
if (instance == nullptr) {
std::lock_guard<std::mutex> lock(mtx);
if (instance == nullptr) {
instance = std::shared_ptr<Singleton>(new Singleton());
}
}
return instance;
}
void doSomething() {
// 示例方法
}
};
// 初始化静态成员变量
std::shared_ptr<Singleton> Singleton::instance = nullptr;
std::mutex Singleton::mtx;
优点:使用智能指针自动管理内存,避免手动释放。
4.总结
推荐使用 Meyer's Singleton(静态局部变量),简洁且线程安全。
如果需要动态内存管理,可以使用智能指针单例模式。
在多线程环境下,务必确保线程安全,可以使用双重检查锁或静态局部变量。
如有错误,敬请指正!!!