【Qt】QObject 派生类的对象所释放内存的方式

1、在 Qt 中,有时候 new 出的对象可以不用亲自去 delete —— QObject 及其派生类的对象,如果其 parent 非0,那么其 parent 析构时会析构该对象。

在 Qt 中,每个 QObject 内部都有一个 list,用来保存所有的 children,当它自己析构时,它同时也会析构掉所有的 children。

2、下面是测试代码:

下面的测试程序在 ATestClass 构造函数中的 m_pTimer 变量 new 的时候有没有传入 this 指针是会不会内存泄漏的关键。如果没有传入 this 指针,则会内存泄漏。

根据第一点的描述,new 出的对象是 m_pTimer,其 paren t是 pTestClass,当 pTestClass 析构的时候,m_pTimer 会自动被析构。所以 ATestClass 无需声明和定义析构函数去析构 m_pTimer。

// 下面是 atestclass.h
#ifndef ATESTCLASS_H
#define ATESTCLASS_H

#include <QTimer>
#include <QObject>

class ATestClass : public QObject
{
    Q_OBJECT
public:
    ATestClass(QObject* parent = nullptr);
    
protected:
    void sltTimeOut();

private:
    QTimer* m_pTimer;
};

#endif // ATESTCLASS_H

// 下面是 atestclass.cpp
#include "atestclass.h"

ATestClass::ATestClass(QObject *parent)
    : QObject(parent)
{
    m_pTimer = new QTimer(this);    // 有没有this很重要
    m_pTimer->setInterval(1000);
    connect(m_pTimer, &QTimer::timeout, this, &ATestClass::sltTimeOut);
    m_pTimer->start();
}

void ATestClass::sltTimeOut()
{

}

// 下面是测试的 main.cpp
#include <QCoreApplication>
#include <QDebug>
#include <QThread>

#include "atestclass.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "begin";

    QThread::sleep(5);

    qDebug() << "begin--";

    for(int i=0; i<1000000; i++)
    {
        ATestClass* pTestClass = new ATestClass();
        delete pTestClass;
    }

    qDebug() << "end---";

    QThread::sleep(5);

    qDebug() << "end";

    return a.exec();
}
3、相关Qt源码

可以在 QObject 的析构函数中看到 d->deleteChildren(); 这句代码。

QObject::~QObject()
{
    ...

    if (!d->children.isEmpty())
        d->deleteChildren();

    qt_removeObject(this);
    if (Q_UNLIKELY(qtHookData[QHooks::RemoveQObject]))
        reinterpret_cast<QHooks::RemoveQObjectCallback>(qtHookData[QHooks::RemoveQObject])(this);

    if (d->parent)        // remove it from parent object
        d->setParent_helper(0);
}

void QObjectPrivate::deleteChildren()
{
    Q_ASSERT_X(!isDeletingChildren, "QObjectPrivate::deleteChildren()", "isDeletingChildren already set, did this function recurse?");
    isDeletingChildren = true;
    // delete children objects
    // don't use qDeleteAll as the destructor of the child might
    // delete siblings
    for (int i = 0; i < children.count(); ++i) {
        currentChildBeingDeleted = children.at(i);
        children[i] = 0;
        delete currentChildBeingDeleted;
    }
    children.clear();
    currentChildBeingDeleted = 0;
    isDeletingChildren = false;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值