在网上查到很多关于Qt 中 QPointer 和 QSharedPointer, 大部分是官方的例子,这里给个实际在对象中使用。
首先介绍一下 QPointer 和 QSharedPointer的简单用法。
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
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
具体例子我打包放到 https://download.csdn.net/download/luodanzhi/10772842
参考:
[Qt内存管理(三) Qt的智能指针](https://blog.csdn.net/yao5hed/article/details/81092152)