Qt 内存回收机制

       关于 Qt 内存回收机制的,刚接触 Qt 不久,第一次看到这方面的问题。这篇文章需要在对Qt有很多了解后才会理解的更透彻。在你不断补充知识时,温故而知新。看到更全面和更官方的内容时随时更新。

         C++ GUI Programming with Qt 4, Second Edition by Jasmin Blanchette; Mark Summerfield 关于内存管理的原话。

           Qt's parent–child mechanism is implemented in QObject. When we create an object (a widget, validator, or any other kind) with a parent, the parent adds the object to the list of its children. When the parent is deleted, it walks through its list of children and deletes each child. The children themselves then delete all of their children, and so on recursively until none remain. The parent–child mechanism greatly simplifies memory management, reducing the risk of memory leaks. The only objects we must call delete on are the objects we create with new and that have no parent. And if we delete a child object before its parent, Qt will automatically remove that object from the parent's list of children.

       在 C++ Primer 中读到 new 是在堆里面申请一段内存资源,new 必须与 delete 成对使用,否则就会造成内存泄漏。但是在Qt中经常可以看见只 new 而不 delete 的情况,这并没有错,Qt 的内存管理机制允许这样的情况存在。

        1、所有继承自 QOBJECT 类的类,如果在 new 的时候指定了父亲,那么它的清理时在父亲被 delete 的时候 delete 的。
        2、程序通常最上层会有一个根的 QOBJECT ,就是放在 setCentralWidget() 中的那个 QOBJECT ,这个 QOBJECT 在 new 的时候不必指定它的父亲,因为这个语句将设定它的父亲为总的 QAPPLICATION ,当整个 QAPPLICATION 没有时它就自动清理,所以也 无需清理。(这里 QT4 和 QT3 有不同,QT3 中用的是 setmainwidget 函数,但是这个函数不作为里面 QOBJECT 的父亲,所以 QT3 中这个顶层的 QOBJECT 要自行销毁)。
        3、这时有人可能会问那如果我自行 delete 掉这些 QT 接管负责销毁的指针了会出现什么情况呢,如果是这样的话,正常情况下 QT 的拥有这个对象的那个父亲会知道这件事情,它会知道它的儿子被你直接 DELETE 了,这样它会将这个儿子移出它的列表,并且重新构建显示内容,但是直接这样做是有风险的! 也就是要说的下一条
        4、当一个 QOBJECT 正在接受事件队列时如果中途被你 DELETE 掉了,就时就出现问题了,所以 QT 中建议大家不要直接DELETE 掉一个 QOBJECT ,如果一定要这样做,要使用 QOBJECT 的 deleteLater() 函数,它会让所有事件都发送完一切处理好后马上清除这片内存,而且就算调用多次的 deletelater 也不会有问题。
        5、QT 不建议在一个 QOBJECT 的父亲的范围之外持有对这个 QOBJECT 的指针,因为如果这样外面的指针很可能不会察觉这个 QOBJECT 被释放,会出现错误,如果一定要这样,就要记住你在哪这样做了,然后抓住那个被你违规使用的 QOBJECT 的destroyed()信号,当它没有时赶快置零你的外部指针。当然我认为这样做是极其麻烦也不符合高效率编程规范的,所以如果要这样在外部持有 QOBJECT 的指针,建议使用引用或者用智能指针,如QT就提供了智能指针针对这些情况,见最后 一条。
        6、QT 中的智能指针封装为 QPointer 类,所有 QOBJECT 的子类都可以用这个智能指针来包装,很多用法与普通指针一样,可以详见 QT assistant
       通过调查这个QT的内存管理功能,发现了很多东西,现在觉得虽然这个QT弄的有点小复杂,但是使用起来还是很方便的,最后要说的是某些内存泄露的检测工具会认为 QT 的程序因为这种方式存在内存泄露,发现时大可不必理会

       原来是因为 qt 对 c++ 的内存管理机制进行了扩充,所有继承自 QObject 的类 new 出来的成员都会自动delete,而手动delete反而会造成不必要的麻烦。

       在c++中如果不手动delete,new对象的内存在进程结束后才会被系统回收,在运行是占用内存越来越多,这就是内存泄露。

 

参考:http://blog.csdn.net/ayangke/article/details/6125741

QTQt)是一个跨平台的C++应用程序开发框架,用于构建桌面、移动和嵌入式应用程序。在QT中,检测和诊断内存泄漏是一个关键任务,因为内存管理不当可能会导致性能下降或程序崩溃。QT提供了工具和方法来帮助开发者查找内存泄漏。 1. **qDebug** 和 **qWarning**:`QDebug`是QT的强大调试工具,可以用于检查内存使用情况。你可以使用`qDebug`来输出内存分配和释放的信息,但这种方法并不直接提供内存泄漏的诊断。 ```cpp QDebug() << "Allocating memory" << new MyClass; delete ptr; // 如果这里不释放,会显示警告 ``` 2. **Memory Debugging Tools**:QT的开发工具如Qt Creator集成了一些内存检测工具。比如,你可以使用`qtcreater`的"Memory Check"选项在运行时进行内存分析,这通常会在指定的代码段执行后检查是否有内存泄漏。 3. **Valgrind**:虽然不是QT的一部分,Valgrind是一个强大的跨平台内存分析工具,可以用来检测内存泄漏。通过将其与QT应用一起使用,你可以得到详细的内存泄漏报告。 ```bash valgrind --leak-check=yes ./your_qt_app ``` 4. **QObjects and Memory Management**:QT的`QObject`类有自动垃圾回收机制,当对象不再被引用时,系统会自动释放内存。然而,如果你手动创建了`QObject`的子类实例,并没有正确地连接信号和槽,或者忘记调用`deleteLater()`,可能会导致内存泄漏。使用`qDelete()`而不是`delete`可以帮助跟踪这些情况。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值