1.什么是对象树?
Qt中的 QObject 会用对象树来组织管理自己,那什么是对象树?
这个概念非常好理解。因为 QObject 类就有一个私有变量 QList<QObject *>,专门存储这个类的子孙后代们。比如创建一个 QObject 并指定父对象时,就会把自己加入到父对象的 children() 列表中,也就是 QList<QObject *> 变量中。
在我们的代码中可以看出,我们每new一个对象,都会给他指定一个父亲,而这个mywidget这个窗体,在构造的收也都要指定一个父亲,就是QWidget。
所以这里面的关系就是QWidget 是myWidget的父亲,myWidget又是btn的父亲。
2.使用对象树模式有什么好处?
好处就是:当父对象被析构时子对象也会被析构。从一定程度上讲,简化了内存回收机制。
举个例子,有一个窗口 Window,里面有 Label标签、TextEdit文本输入框、Button按钮这三个元素,并且都设置 Window 为它们的父对象。这时候我做了一个关闭窗口的操作,作为程序员的你是不是自然想到将所有和窗口相关的对象析构啊?古老的办法就是一个个手动 delete 呗。是不是很麻烦?Qt 运用对象树模式,当父对象被析构时,子对象自动就 delete 掉了,不用再写一大堆的代码了。
所以,在我点击该运行程序的X后,系统会根据这个树状的结构,释放掉整个结构的内存。
3.对象树的问题(代码示例)
如果子对象,由于系统机制,会自动释放,那么可能存在一个问题,子对象被二次释放,从而导致崩溃
如下图示例:
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPushButton button;
Widget w;
button.setParent(&w);
button.setText("QT崩溃");
w.show();
return a.exec();
}
在本例中,button和w按照顺序存放在栈里,而我们栈有先进后出的特性,正因如此,我们的程序结束后,系统会先释放w的内存,再释放button的内存,在释放w的内存时候由于 button变量绑定了父变量w(button.setParent(&w);),button也会和w一起释放,因此button在本例中会进行两次释放,从而导致奔溃,如下图所示:
解决办法:将存入栈的顺序改变,让button后存入栈,也就是把button定义在w的后面,以至于程序结束后,先释放button再释放w。就不会有二次释放的情况。
今天的分享到此结束,希望通过这篇文章大家对对象树,有更加深层次的理解。希望大家给一个免费的关注和赞吧,笔者也会更加努力,写出更加优质的技术分享文章!!