zl程序教程

您现在的位置是:首页 >  工具

当前栏目

Qt 中信号参数:QSharedPointer (智能指针类型)

Qt智能 类型 参数 指针 信号
2023-09-11 14:16:46 时间

智能指针作为信号参数
再谈QSharedPointer
Demo 1
Demo 2
智能指针作为信号参数
/*! connect a module to the event bus
*/
Q_DECLARE_METATYPE( QSharedPointer<GitlEvent> )
bool GitlEventBus::registerModule(GitlModuleDelegate* pcModule)
{    
    qRegisterMetaType< QSharedPointer<GitlEvent> >("QSharedPointer<GitlEvent>");
    connect(this,     SIGNAL(eventTriggered(QSharedPointer<GitlEvent>) ),
            pcModule, SLOT  (detonate      (QSharedPointer<GitlEvent>) ),
            Qt::AutoConnection );

    return true;
}

/*! send event to event bus
*/
void GitlEventBus::post(const GitlEvent& rcEvt) const
{    
    QSharedPointer<GitlEvent> pcEvtCopy( rcEvt.clone() );

    /// notify modules
    emit eventTriggered(pcEvtCopy);
}


当我第一次看到这么用的时候,是一脸懵逼的。

qt中的信号的入参的类型,必须为 meta type,即元类型。即能够让moc识别的类型。
将该智能指针 注册为 元类型了。这样在信号中,就能够使用该智能指针的类型了

再谈QSharedPointer
一个共享指针, 实现的是引用计数型的智能指针
可以被自由地拷贝和复制,在任意的地方共享它,所以QSharedPointer也可以用作容器元素, 及用作QMap的元素,但不能用作key,QSharedPointer与QMap混合使用的注意事项
计数型指针,在内部QSharedPointer对拥有的内存资源进行引用计数,比如有3个QSharePointer同时指向一个内存资源,那么就计数3, 直到引用计数下降到0,那么就自动去释放内存。
QSharedPointer是线程安全的,但是QSharedPointer指向的内存区域可不一定是线程安全的,所以过个线程同时修改QSharedPointer指向的数据时,还是应该要考虑加锁
Demo 1
参考Demo

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QDebug>
#include <QSharedPointer>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE


class Student : public QObject
{
    Q_OBJECT;
public:
    Student(QObject *parent = nullptr);

    ~Student();

};

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
    QSharedPointer<Student> m_pStudent;
};
#endif // WIDGET_H

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    qDebug()<<__FUNCTION__;
    m_pStudent = QSharedPointer<Student>(new Student(this)); //m_pStudent = QSharedPointer<Student>(new Student());

}

Widget::~Widget()
{
    qDebug()<<__FUNCTION__;
    delete ui;
}


Student::Student(QObject *parent)
{
    qDebug() << __FUNCTION__;
}

Student::~Student()
{
    qDebug() << __FUNCTION__;
}


关闭窗口时,输出:

Widget
Student
~Widget
~Student

Demo 2
Qt QPointer和 QSharedPointer使用实例
该例子更好的说明了在QSharedPointer 在资源耗尽时,如何自动调用对象的析构函数。

Person.h
class Person :  public QObject
{
    Q_OBJECT
public:
    Person(const QString &name, QObject *parent = nullptr);
    virtual ~Person();
    QString name() const;
    void setName(const QString &name);
 
private:
    QString m_name; // 名字
};

Person.cpp
Person::Person(const QString &name, QObject *parent) : QObject(parent)
{
    m_name = name;
    qDebug() << "create a person: " << m_name;
}
 
 
Person::~Person()
{
    qDebug() << "delete a person: " << m_name;
}
 
QString Person::name() const
{
    return m_name;
}
 
void Person::setName(const QString &name)
{
    m_name = name;
}

Window.h
class MainWindow : public QMainWindow
{
    Q_OBJECT
 
public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
 
private:
    QList<QPointer<Person>> m_persons;
    QSharedPointer<Person> m_person;
 
};

Window.cpp

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    qDebug() << m_person;
    m_persons.append(new Person("person1"));
    m_persons.append(new Person("person2"));
 
 
    QPointer<Person> tmp = new Person("tmp");
    // need delelet tmp
    delete tmp;
    QSharedPointer<Person> sharedPerson(new Person("sharedPerson"));
    m_person = sharedPerson;
}
 
MainWindow::~MainWindow()
{
    qDebug("call ~Mainwindow");
    // 释放拥有的 children
    qDeleteAll(m_persons);
    m_persons.clear();
    // m_person 被释放,这就是智能指针
 
}

output
QSharedPointer(QObject(0x0))
create a person:  "person1"
create a person:  "person2"
create a person:  "tmp"
delete a person:  "tmp"
create a person:  "sharedPerson"
call ~Mainwindow
delete a person:  "person1"
delete a person:  "person2"
delete a person:  "sharedPerson"