前言
单例模式(创建型设计模式)的 C++ 代码示例模板。
代码仓库
单例模式(Singleton)
结构
- 单例类
- 私有静态单例对象
- 私有构造方法
- 公有静态获取单例对象方法
返回引用的原因:保证是同一单例对象而不是副本;减少返回值的拷贝开销;返回值拷贝被删除
设置为私有:允许类内将单例对象作为参数或返回值传递(公有静态获取单例对象方法 可以返回值而不是引用)
设置为删除:禁止拷贝
设置为私有和删除:禁止拷贝
核心
- 私有静态单例对象:单例类内保存同一单例对象
- 私有构造方法:禁止客户端创建多个单例对象
- 公有静态获取单例对象方法:允许客户端创建或获取同一单例对象
一般 饿汉式是获取,懒汉式是创建或获取。
- 私有或删除拷贝构造方法和拷贝赋值运算符:禁止客户端或单例类内创建一个或多个拷贝单例对象
类型
饿汉式
- 程序启动时(main() 执行前) 创建单例对象(不管用不用都提前创建)
- 在类外初始化私有静态单例对象(保证在程序启动时(main() 执行前)创建单例对象)
在类外初始化私有静态单例对象 注意:
静态非 const 整数类型(short 和 int 等) 或 静态非 constexpr 内置类型(char 和 float 等)的成员属性 只能在类外初始化;
因为构造方法是私有权限,所以在类外只能是隐式调用无参构造方法;
如果单例类需要传参并初始化成员属性,可以考虑额外 定义设置成员属性方法 或 在公有静态获取单例对象方法中设置成员属性
- 线程安全
- 公有静态获取单例对象方法直接返回单例对象(因为在程序启动时(main() 执行前)已经创建单例对象,且线程安全,无需其他逻辑)
- 创建或获取单例对象时使用引用
使用引用的原因:保证是同一单例对象而不是副本;减少返回值的拷贝开销;返回值拷贝被删除
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| #include <iostream>
using std::cout; using std::endl;
class Singleton { public: ~Singleton() = default;
inline static Singleton &getInstance() { return singleton; }
private: Singleton() { cout << "Singleton()" << endl; }
Singleton(const Singleton &) = delete; Singleton &operator=(const Singleton &) = delete;
static Singleton singleton; };
Singleton Singleton::singleton;
int main() { Singleton &singleton_1 = Singleton::getInstance(); Singleton &singleton_2 = Singleton::getInstance();
cout << "Singleton_1: " << &singleton_1 << endl; cout << "Singleton_2: " << &singleton_2 << endl;
return 0; }
|
懒汉式
- 程序运行时创建单例类对象(需要用了才创建)
- 在类外初始化私有静态单例对象 和 私有静态互斥锁(保证在程序运行时创建单例类对象)
在类外初始化私有静态单例对象 和 互斥锁 注意:
静态非 const 整数类型(short 和 int 等) 或 静态非 constexpr 内置类型(char 和 float 等)的成员属性 只能在类外初始化;
因为构造方法是私有权限,所以在类外只能是隐式调用无参构造方法;
如果单例类需要传参并初始化成员属性,可以考虑额外 定义设置成员属性方法 或 在公有静态获取单例对象方法中设置成员属性
- 线程不安全(如多个线程同时调用公有静态获取单例对象方法)
- 公有静态获取单例对象方法使用 私有静态互斥锁 和 双重检查锁定(保证线程安全)
- 创建或获取单例对象时使用引用
使用引用的原因:保证是同一单例对象而不是副本;减少返回值的拷贝开销;返回值拷贝被禁止
代码(懒汉式)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| #include <iostream> #include <memory> #include <mutex>
using std::cout; using std::endl; using std::lock_guard; using std::make_unique; using std::mutex; using std::unique_ptr;
class Singleton { public: ~Singleton() = default;
static Singleton &getsingleton() { if (singleton == nullptr) { lock_guard<mutex> mutex_lock_guard(mutex_lock);
if (singleton == nullptr) { singleton = make_unique<Singleton>(); }
}
return *singleton; }
private: Singleton() { cout << "Singleton()" << endl; }
Singleton(const Singleton &) = delete; Singleton &operator=(const Singleton &) = delete;
static unique_ptr<Singleton> singleton;
static mutex mutex_lock;
friend unique_ptr<Singleton> make_unique<Singleton>(); };
unique_ptr<Singleton> Singleton::singleton = nullptr; mutex Singleton::mutex_lock;
int main() { Singleton &singleton_1 = Singleton::getsingleton(); Singleton &singleton_2 = Singleton::getsingleton();
std::cout << "Singleton_1: " << &singleton_1 << std::endl; std::cout << "Singleton_2: " << &singleton_2 << std::endl;
return 0; }
|
总结
单例模式(创建型设计模式)的 C++ 代码示例模板。
参考资料
作者的话
- 感谢参考资料的作者/博主
- 作者:夜悊
- 版权所有,转载请注明出处,谢谢~
- 如果文章对你有帮助,请点个赞或加个粉丝吧,你的支持就是作者的动力~
- 文章在描述时有疑惑的地方,请留言,定会一一耐心讨论、解答
- 文章在认识上有错误的地方, 敬请批评指正
- 望读者们都能有所收获