如果qt的信号和槽之间发送的是对象,对象传递过程中会发生拷贝操作。
一、跨线程之间
#ifndef __MAIN_WINDOW_H_
#define __MAIN_WINDOW_H_
#include <QMainWindow>
#include <QThread>
#include <QPushButton>
#include "InheritObject.h"
class MainWindow:public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private slots:
void on_sendObject_clicked();
signals:
void sendObject(MyObject);
private:
QThread *m_th;
InheritObject *m_obj;
void InitUi();
};
#endif __MAIN_WINDOW_H_
#include "MainWindow.h"
#include <QGridLayout>
#include <QDebug>
#include "MyObject.h"
MainWindow::MainWindow(QWidget *parent):QMainWindow(parent)
{
qDebug()<<"GUI thread = "<<QThread::currentThreadId();
InitUi();
m_th = new QThread();
m_obj = new InheritObject();
m_obj->moveToThread(m_th);
connect(this,&MainWindow::sendObject,m_obj,&InheritObject::onReceiveObject);
//启动线程,线程默认开启事件循环,并且线程正处于事件循环状态
m_th->start();
}
void MainWindow::InitUi()
{
QWidget *pWidget = new QWidget(this);
QGridLayout *pLayout = new QGridLayout();
QPushButton *pSendObject = new QPushButton("SendObject",this);
pLayout->addWidget(pSendObject,0,0);
connect(pSendObject,&QPushButton::clicked,this,&MainWindow::on_sendObject_clicked);
pWidget->setLayout(pLayout);
this->setCentralWidget(pWidget);
}
void MainWindow::on_sendObject_clicked()
{
MyObject myObject;
myObject.age = 23;
myObject.name = "wangjian";
emit sendObject(myObject);
}
#ifndef __INHERIT_OBJECT_H_
#define __INHERIT_OBJECT_H_
#include <QObject>
#include "MyObject.h"
class InheritObject:public QObject
{
Q_OBJECT
public:
explicit InheritObject(QObject *parent = 0);
public slots:
void onReceiveObject(MyObject object);
};
#endif
#include "InheritObject.h"
#include <QDebug>
#include <QThread>
InheritObject::InheritObject(QObject *parent):QObject(parent)
{
}
void InheritObject::onReceiveObject(MyObject object)
{
qDebug()<<(QString(" %1 %2 ").arg(object.age).arg(object.name));
}
#ifndef __MY_OBJECT_H_
#define __MY_OBJECT_H_
#include <QObject>
#include <QDebug>
#include <QThread>
class MyObject
{
public:
MyObject()
{
qDebug()<<"function "<<__FUNCTION__<<this<<QThread::currentThreadId();
}
MyObject(const MyObject& object)
{
qDebug()<<"function copy "<<__FUNCTION__<<this<<QThread::currentThreadId();
this->age = object.age;
this->name = object.name;
}
~MyObject()
{
qDebug()<<"function "<<__FUNCTION__<<this<<QThread::currentThreadId();
}
int age;
QString name;
};
#endif
#include <QApplication>
#include "MainWindow.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
qRegisterMetaType<MyObject>("MyObject");
MainWindow w;
w.show();
return app.exec();
}
运行结果
GUI thread = 0x17e0
function MyObject::MyObject 0x2a6e74a248 0x17e0 //栈对象创建
function copy MyObject::MyObject 0x2a6e74a258 0x17e0 //emit发送信号的时候进行一次拷贝
function copy MyObject::MyObject 0x1ed09d9ffb0 0x17e0 //发送信号,没有被槽函数立即执行,存到信息队列,进行一次拷贝
function MyObject::~MyObject 0x2a6e74a258 0x17e0 //emit发送完成,对象销毁
function copy MyObject::MyObject 0x2a6eefb9a0 0x201c//槽函数从消息队列中,获取到消息,进行一次拷贝,是在槽函数对应的线程中
function MyObject::~MyObject 0x2a6e74a248 0x17e0//栈对象销毁
" 23 wangjian "
function MyObject::~MyObject 0x2a6eefb9a0 0x201c//槽函数执行完成,对象销毁
function MyObject::~MyObject 0x1ed09d9ffb0 0x201c//消息队列中对象销毁
二、在同一个线程
改一下connect的最后一个连接参数,由自动改为Qt::DirectConnection
connect(this,&MainWindow::sendObject,m_obj,&InheritObject::onReceiveObject);
改为
connect(this,&MainWindow::sendObject,m_obj,&InheritObject::onReceiveObject,Qt::DirectConnection);
运行结果
GUI thread = 0x2980
function MyObject::MyObject 0xd99f4fa5f8 0x2980 //栈对象创建
function copy MyObject::MyObject 0xd99f4fa608 0x2980//发送信号进行一次拷贝
function copy MyObject::MyObject 0xd99f4fa440 0x2980//槽函数执行进行一次拷贝
" 23 wangjian "
function MyObject::~MyObject 0xd99f4fa440 0x2980//槽函数结束,对象销毁
function MyObject::~MyObject 0xd99f4fa608 0x2980//发送完信号,对象销毁
function MyObject::~MyObject 0xd99f4fa5f8 0x2980//栈对象销毁