Qt的内存管理机制

QObject的parent设置为null
1.如果构造时直接指定了null,当前实例不会有父对象存在,Qt也不能自动析构该实例,除非实例超出作用域导致析构函数被调用,使用deletelater()函数,不建议使用delete
2.如果指定了parent,而又将它设置为null,那么当前实例会从父对象children中删除,不受到QObject&parent机制影响。
3.对于QWidget,parent为NULL时代表其为一个顶层窗口,QDialog,当parent不为NULL时他会显示在父widget中心区域的上层;如果QWidget的parent为NULL或是其他值,在其加入布局管理器或者QMainWindow设置widget时,会自动将parent设置为相应的父widget,在父控件销毁时这些子控件以及布局管理器对象会一并销毁。所有QWidget加入布局管理器或者QMainWindow设置widget时,就不需要手动释放其内存了,否则二次释放会崩溃。
4.对于在局部作用域上创建的父对象及其子对象,要注意对象销毁的顺序,因为父对象销毁时也会销毁子对象,当子对象会在父对象之后被销毁时会引发double free。
QWidget的内存释放:
1.使用QObject Parent机制
QWidget也是QObject的子类,所以在parent机制上是没有区别的,这种情况下可以上面二中描述是一样的
2.设置Qt::WA_DeleteOnClose
当你想让关闭窗口的时候,让窗口销毁,在构造函数中设置Qt::WA_DeleteOnClose标志:setAttribute(Qt::WA_DeleteOnClose);对于单纯显示而不需要和父控件做交互的widget,直接设置DeleteOnClose即可,close时widget会被自动析构。
3. 重写QCloseEvent事件
//delete this;//会发生崩溃
this->deletelater();
4. qDeleteAll和clear 针对容器的回收
QList<Def*> defs;
qDeleteAll(defs);
defs.clear();
QObjectCleanupHandler:
Qt 对象清理器是实现自动垃圾回收的很重要的一部分。QObjectCleanupHandler可以注册很多子对象,并在自己删除的时候自动删除所有子对象。同时,它也可以识别出是否有子对象被删除,从而将其从它的子对象列表中删除。这个类可以用于不在同一层次中的类的清理操作,例如,当按钮按下时需要关闭很多窗口,由于窗口的 parent 属性不可能设置为别的窗口的 button,此时使用这个类就会相当方便。

testMemory::testMemory(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);
    m_clearupHandler = new QObjectCleanupHandler;
}
testMemory::~testMemory()
{
    qDebug() << "~testMemory()---------------------------";
    delete m_clearupHandler;
    qDebug() << "m_btnVec size: " << m_btnVec.size();//3
    qDebug() << "m_btnVec data:  " << m_btnVec[0]->text();//崩溃 因为QPushButton*已经被delete
}
void testMemory::on_addPushBtn_clicked() {
    int size = m_btnVec.size() + 1;
    QPushButton* btn = new QPushButton;
    btn->setText(QString::number(size));
    m_btnVec.push_back(btn);
    m_clearupHandler->add(btn);
    qDebug() << "m_btnVec size:  " << m_btnVec.size();
}
void testMemory::on_deletePushBtn_clicked() {
    qDeleteAll(m_btnVec);
    qDebug() << "on_deletePushBtn_clicked---------------m_btnVec size: " << m_btnVec.size();;//3
    qDebug() << "m_btnVec data:  " << m_btnVec[0]->text();//崩溃 QPushButton* 被delete
    m_btnVec.clear();//qDeleteAll delete指针 需要手动清空qvector
    }

引用计数
应用计数是最简单的垃圾回收实现:每创建一个对象,计数器加 1,每删除一个则减 1。
在这里插入图片描述
利用Qt的信号槽机制,在对象销毁的时候自动减少计数器的值。但是,我们的实现并不能防止对象创建的时候调用了两次attach()。
在这里插入图片描述
现在我们的实现已经可以做到防止一个对象多次调用 attach() 和 detach() 了。然而我们不能保证对象一定会调用 attach() 函数进行注册。毕竟,这不是 C++ 内置机制。有一个解决方案是,重定义 new 运算符(这一实现同样很复杂,不过可以避免出现有对象不调用 attach() 注册的情况)。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值