基本概念
QPointer提供了模板类,这个包含指针主要是针对于QObject。
当对象被销毁的时候会被自动设置为0,解决了指针悬挂问题。这里QPointer<T>中的T必须是QObject的子类,也就是identity type的Qt类。
QPinter的删除
对象树不能解决指针悬挂的问题:
1. QPointer为QObject提供了保护指针;
2. 当引用的对象被销毁时,QPointer会被设置为0;
3. 能适应任意的指针(保护指针自动转换为指针类型);
官方例子:
// ExampleObject is just QObject subclass
QPointer<ExampleQObject> object(new ExampleQObject);
delete object;
if (object)
qDebug() << ”Dangling pointer";
else
qDebug() << "No dangling pointer";
这里本人做了一个涉及QPointer的实例
程序运行截图如下:
生产者生产数据,这个数据是QObject。然后有4-5个消费者去消费,在拿数据的时候加个锁,避免并发拿数据时出现问题:
QObject* ProjectData::getItem()
{
mutex.lock();
if(m_objList.size() == 0){
mutex.unlock();
return nullptr;
}
QObject *ret = m_objList[0];
m_objList.removeFirst();
mutex.unlock();
return ret;
}
关键代码如下:
消费者线程:
#include "WorkerThread.h"
#include "ProjectData.h"
#include <QPointer>
#include <QTime>
WorkerThread::WorkerThread()
{
stopFlag = false;
qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
}
void WorkerThread::setProjectData(ProjectData *project)
{
m_project = project;
}
void WorkerThread::run()
{
while(true){
if(stopFlag){
QThread::sleep(1);
break;
}
QPointer<QObject> ptr = m_project->getItem();
if(!ptr){
QThread::sleep(1);
continue;
}
//开始处理数据
int disposeTime = qrand() % 5;
qDebug() << "线程:" << QThread::currentThread() << "处理" << ptr << " 需要" << disposeTime << "S";
QThread::sleep(disposeTime);
delete ptr;
//qDebug() << "ptr" << ptr;
}
}
调用及退出:
#include <QCoreApplication>
#include <QTimer>
#include <QObject>
#include <QEventLoop>
#include "WorkerThread.h"
#include "ProjectData.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
ProjectData *p = new ProjectData;
//设置消费者线程
WorkerThread *p1 = new WorkerThread;
WorkerThread *p2 = new WorkerThread;
WorkerThread *p3 = new WorkerThread;
WorkerThread *p4 = new WorkerThread;
WorkerThread *p5 = new WorkerThread;
p1->setProjectData(p);
p2->setProjectData(p);
p3->setProjectData(p);
p4->setProjectData(p);
p5->setProjectData(p);
p1->start();
p2->start();
p3->start();
p4->start();
p5->start();
//设置生产者生产者
QTimer timer;
QObject::connect(&timer, &QTimer::timeout, [=](){
QObject *test = new QObject;
test->setObjectName("新数据ABC");
p->addItem(test);
qDebug() << "当前剩余资源:" << p->getSize();
});
timer.start(300);
QTimer::singleShot(1000 * 20, [=]{
p1->stopFlag = true;
p2->stopFlag = true;
p3->stopFlag = true;
p4->stopFlag = true;
p5->stopFlag = true;
QEventLoop loop;
QTimer::singleShot(1000 * 5, &loop, SLOT(quit()));
loop.exec();
delete p;
qDebug() << "退出";
qApp->quit();
});
return a.e
源码打包下载地址:
https://github.com/fengfanchen/Qt/tree/master/QPointerMutiThread