一杯清酒邀明月
天下本无事,庸人扰之而烦耳。
posts - 3121,comments - 209,views - 578万

最简单的写法:

1 static MyClass* MyClass::Instance()
2 {
3     static MyClass inst;
4     return &inst;
5 }

过去很长一段时间一直都这么写,简单粗暴有效。但是直接声明静态对象会使编译出的可执行文件增大,也有可能出现其他的一些问题,所以利用了Qt自带的智能指针QScopedPointer和线程锁QMutex,改成了需要时才动态初始化的模式:

复制代码
 1 static MyClass* MyClass::Instance()
 2 {
 3     static QMutex mutex;
 4     static QScopedPointer<MyClass> inst;
 5     if (Q_UNLIKELY(!inst)) {
 6         mutex.lock();
 7         if (!inst) {
 8             inst.reset(new MyClass);
 9         }
10         mutex.unlock();
11     }
12     return inst.data();
13 }
复制代码

既保证了线程安全又防止了内存泄漏,效率也没降低太多,简直完美。

可惜每次都要重复这么几行实在麻烦,于是写了一个模板类:

复制代码
 1 template <class T>
 2 class Singleton
 3 {
 4 public:
 5     static T* Instance()
 6     {
 7         static QMutex mutex;
 8         static QScopedPointer<T> inst;
 9         if (Q_UNLIKELY(!inst)) {
10             mutex.lock();
11             if (!inst) {
12                 inst.reset(new T);
13             }
14             mutex.unlock();
15         }
16         return inst.data();
17     }
18 };
复制代码

使用的时候直接这样——

MyClass* inst = Singleton<MyClass>::Instance();

除了用模板类,还可以利用c++中强大的宏:

复制代码
 1 #define DECLARE_SINGLETON(Class) \
 2 Q_DISABLE_COPY(Class) \
 3 public: \
 4     static Class* Instance() \
 5     { \
 6         static QMutex mutex; \
 7         static QScopedPointer<Class> inst; \
 8         if (Q_UNLIKELY(!inst)) { \
 9             mutex.lock(); \
10             if (!inst) inst.reset(new Class); \
11             mutex.unlock(); \
12         } \
13         return inst.data(); \
14     }
复制代码

然后声明的时候,填加一行这个宏:

1 class MyClass
2 {
3     DECLARE_SINGLETON(MyClass);    // 声明单例模式
4     //...
5 }

好评好评。

当然,为了要保证真的是单例模式,还要把构造函数限制为private,不然以后什么时候忘记了这码事,在外面又new了一下就不好了。

另外Qt本身自带了一个宏Q_GLOBAL_STATIC,也有类似单例模式的效果,QThreadPool::globalInstance()函数的实现就是利用了这个宏。不过它的主要用处是声明全局变量,和Singleton还是有差别的。

posted on   一杯清酒邀明月  阅读(3686)  评论(0编辑  收藏  举报
编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
历史上的今天:
2020-06-22 Qt 对话框窗体关闭时,如何自动销毁窗体类对象、清空内存
< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5

点击右上角即可分享
微信分享提示