参考了网上的一些单例模式,自己也写一个模板。
要点:
- 线程安全性
- 单例对象的唯一性
cpp
#include <mutex>
//在模板类 Singleton 中,可以定义单例模式的实现细节
template <typename T>
class Singleton {
public:
//通过删除拷贝构造函数、赋值运算符、移动构造函数、移动赋值运算符等函数,确保了单例对象的唯一性
Singleton(const Singleton &) = delete; //删除 拷贝构造函数
Singleton& operator=(const Singleton &) = delete; //删除 赋值运算符
Singleton(Singleton &&) = delete; //删除 移动构造函数
Singleton& operator=(Singleton &&) = delete; //删除 移动赋值运算符
//通过静态函数 instance() 返回单例对象的指针,并利用静态成员变量和静态成员函数确保单例对象的唯一性和线程安全性
static T* instance()
{
static T object;
return &object;
}
protected:
Singleton() = default;
virtual ~Singleton() = default;
};
以下为使用例子
cpp
//利用了 C++ 中的模板元编程技术,将单例模式的实现逻辑延迟到了模板类中,使得 MyClass 类只需专注于自身的业务逻辑而不必关心单例模式的细节
class MyClass: public Singleton<MyClass>
{
private:
//通过友元关系确保 Singleton 类能够访问 MyClass 的私有构造函数,从而限制了对 MyClass 对象的实例化
friend class Singleton<MyClass>;
MyClass() = default;
~MyClass() = default;
public:
// ... 其他成员函数和数据成员
};
int main() {
MyClass* obj1 = Singleton<MyClass>::instance();
MyClass* obj2 = Singleton<MyClass>::instance();
// obj1 和 obj2 指向同一个 MyClass 对象
return 0;
}
这种实现方式提供了一种简洁而且易于使用的单例模式实现方式
- 将单例模式的实现细节与具体的业务逻辑分离,增强了代码的可读性和可维护性
- 每次调用 Singleton::instance() 都会获取到同一个 MyClass 类的单例对象指针
- 使用了静态局部变量的初始化来保证多线程环境下的线程安全性,在C++11之后,静态局部变量的初始化是线程安全的。编译器会负责确保静态局部变量只被初始化一次,并且在多线程环境下保证线程安全
- 通过删除拷贝构造函数、赋值运算符、移动构造函数、移动赋值运算符等函数,确保了单例对象的唯一性
参考文章:
设计模式之单例模式(C++实现)
C++单例模式模板 (简单易懂且有效)
C++11中静态局部变量初始化的线程安全性