目录
需求
单例模式
Qt单例模式示例模板(此版本重大bug)
bug(感谢网友大神:火龙 的帮助)
源文件(修复完bug)
Qt单例模式示例模板(修复bug后的单例模式代码2:使用原子caozuo)
需求
Qt常需要一个类,全局调用,是设计模式中的单例模式。
单例模式
单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。
显然单例模式的要点有三个;
一是某个类只能有一个实例;
二是它必须自行创建这个实例;
三是它必须自行向整个系统提供这个实例。
Qt单例模式示例模板(此版本重大bug)
使用DbService::instance()全局获取该对象
头文件
#ifndef DBSERVICE_H
#define DBSERVICE_H
#include <QObject>
#include <QMutex>
#include <QMutexLocker>
class DbService : public QObject
{
Q_OBJECT
public:
explicit DbService(QObject *parent = 0);
public:
static DbService * instance();
signals:
public slots:
protected:
private:
static DbService *_pInstance;
static QMutex _mutex;
};
#endif // DBSERVICE_H
源文件(存在bug)
#include "DbService.h"
DbService * DbService::_pInstance = 0;
QMutex DbService::_mutex;
DbService::DbService(QObject *parent) : QObject(parent)
{
}
DbService * DbService::instance()
{
if(!_pInstance)
{
QMutexLocker lock(&_mutex);
if(!_pInstance)
{
_pInstance = new DbService();
}
}
return _pInstance;
}
bug(感谢网友大神:火龙 的帮助)
_pInstance = new DbService();
1. 申请DbService的内存
2. 在申请的内存上构造DbService
3. 将_pInstance指针指向这个内存
这个new有这么三步
编译器可能是132这么执行的,多个线程第一次同时使用时,可能出现野指针,即编译器先指向内存(准备第三步构造)时,另一个线程获取,则出现野指针,运行出现段错误。
源文件(修复完bug)
#include "DbService.h"
DbService * DbService::_pInstance = 0;
QMutex DbService::_mutex;
DbService::DbService(QObject *parent) : QObject(parent)
{
}
DbService * DbService::instance()
{
if(!_pInstance)
{
QMutexLocker lock(&_mutex);
if(!_pInstance)
{
DbService *pInstance = new DbService(); // 修改处
_pInstance = pInstance; // 修改处
}
}
return _pInstance;
}
Qt单例模式示例模板(修复bug后的单例模式代码2:使用原子caozuo)
头文件
#ifndef DBSERVICE_H
#define DBSERVICE_H
#include <QObject>
#include <QMutex>
#include <QMutexLocker>
class DbService : public QObject
{
Q_OBJECT
public:
explicit DbService(QObject *parent = 0);
public:
static DbService &getInstance();
signals:
public slots:
protected:
private:
static QAtomicPointer<DbService> _instance;
static QMutex _mutex;
};
#endif // DBSERVICE_H
源文件
#include "DbService.h"
QAtomicPointer<DbService> DbService::_instance = 0;
QMutex DbService::_mutex;
DbService::DbService(QObject *parent) : QObject(parent)
{
}
DbService * DbService::instance()
{
#ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
if(!QAtomicPointer::isTestAndSetNative())//运行时检测
qDebug() << "Error: TestAndSetNative not supported!";
#endif
//使用双重检测。
/*! testAndSetOrders操作保证在原子操作前和后的的内存访问
* 不会被重新排序。
*/
if(_instance.testAndSetOrdered(0, 0))//第一次检测
{
QMutexLocker locker(&mutex);//加互斥锁。
_instance.testAndSetOrdered(0, new DbService);//第二次检测。
}
return _instance;
}
欢迎技术交流和帮助,提供IT相关服务,索要源码请联系博主QQ: 21497936,若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/80046081
————————————————
版权声明:本文为CSDN博主「红模仿_红胖子」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq21497936/article/details/80046081