Qt QPointer 和 QSharedPointer 使用实例

 

 

在网上查到很多关于Qt 中 QPointer 和 QSharedPointer, 大部分是官方的例子,这里给个实际在对象中使用。

首先介绍一下 QPointer 和 QSharedPointer的简单用法。

QPointer

QPointer can only point to QObject instances. It will be automatically set to nullptr if the pointed to object is destroyed. It is a weak pointer specialized for QObject. 

简单理解为,为指向QObject提供了一层包装,和C++传统指针一样的方法,但可以避免 “野” 指针。可以大胆的使用。

QObject *obj = new QObject;
QPointer pObj(obj);
delete obj;
Q_ASSERT(pObj.isNull()); // pObj will be nullptr now

QSharedPointer

A reference-counted pointer. The actual object will only be deleted, when all shared pointers are destroyed. Equivalent to std::shared_ptr.

简单说就是不用了,就释放了。

int *pI = new int;
QSharedPointer pI1(pI);
QSharedPointer pI2 = pI1;
pI1.clear();
// pI2 is still pointing to pI, so it is not deleted
pI2.clear();
// No shared pointers anymore, pI is deleted

综合例子

1.  建立一个person 对象,这里简化只有一个成员 name。

 

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;
}

为了更加明白说明时候释放对象,我们建立一个MainWindow类, 下面是代码

 

头文件

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    QList> m_persons;
    QSharedPointer m_person;

};
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    qDebug() << m_person;
    m_persons.append(new Person("person1"));
    m_persons.append(new Person("person2"));


    QPointer tmp = new Person("tmp");
    // need delelet tmp
    delete tmp;
    QSharedPointer sharedPerson(new Person("sharedPerson"));
    m_person = sharedPerson;
}

MainWindow::~MainWindow()
{
    qDebug("call ~Mainwindow");
    // 释放拥有的 children
    qDeleteAll(m_persons);
    m_persons.clear();
    // m_person 被释放,这就是智能指针

}

 

最后的打印结果是

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"

分析结果, 在使用QPointer 的QList中,释放的时候用QList管理,调用qDeleteAll(), 不调用不会调用person的析构函数,正常使用的QObject对象指针都是有parent的,所以不需要专门调用qDeleteAll。然后为了单独验证QPointer, 专门生成了tmp, 这个必须delete。如果不确定被其他得放释放,调用 tmp.isNull() 判断一下。

m_person 指向了 QSharedPointer,这个使用就像一个普通的对象一样,都没有调用 m_person.clear(),这样,在多个实例中共享 m_person 就不需要想着哪儿忘了释放了。

具体例子我打包放到 https://download.csdn.net/download/luodanzhi/10772842

 

参考:

[Qt内存管理(三) Qt的智能指针](https://blog.csdn.net/yao5hed/article/details/81092152)

你可能感兴趣的:(Qt学习)