zoukankan      html  css  js  c++  java
  • Qt 单例模式的实现(4种方法)

    最简单的写法:

    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还是有差别的。

  • 相关阅读:
    学python走过的坑 二 element与elements的却别
    Python 进度条显示
    学python走过的坑一 类的实例化
    shell打印 菱形
    shell打印 倒等腰三角形
    互联网协议入门
    shell应用之批量添加用户实例
    Centos7不修改默认交换分区下添加交换分区
    shell中处理用户输入
    sed命令的介绍
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/14919155.html
Copyright © 2011-2022 走看看