代码语言:javascript复制我们不妨看看以下小例子。
QWidget window;
QPushButton *button1 = new QPushButton("One");
QPushButton *button2 = new QPushButton("Two");
QPushButton *button3 = new QPushButton("Three");
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
window.setLayout(layout);
window.show();
qDebug() << "Window children:" << window.children();
可以看到QPushButton和QHBoxLayout控件在new完后不需要执行delete操作。究竟是为何呢?我们再看看打印输出:
代码语言:javascript复制Window children: (QHBoxLayout(0x1f32ebc0), QPushButton(0x1f48ea00), QPushButton(0x1f48e9c0), QPushButton(0x1f48e580))
打印输出可以看到window
对象下有QHBoLayout和3个QPushButton子控件,意味着当window对象析构时会先析构其下的所有子控件,所以就不需要手动删除了。
为了进一步验证,君君为大家奉上其Qt的实现源码。
QWidget的setLayout源码中可以看到布局控件(QLayout)对象最终会设置自己的父类为QWidget。
代码语言:javascript复制/* 省略部分无关代码 */
void QWidget::setLayout(QLayout *l)
{
...
if (oldParent != this) {
l->setParent(this);
l->d_func()->reparentChildWidgets(this);
l->invalidate();
}
}
QLayout的addWidget内部实现是传入的w
对象最终也会设置其QLayout的parentWidget()
对象。
void QLayout::addWidget(QWidget *w)
{
addChildWidget(w);
addItem(QLayoutPrivate::createWidgetItem(this, w));
}
void QLayout::addChildWidget(QWidget *w)
{
QWidget *mw = parentWidget();
QWidget *pw = w->parentWidget();
...
if (!pw && mw)
w->setParent(mw);
...
}
最后经过一轮花里胡哨的操作,最后QHBoxLayout和QPushButton控件都有一个共同的父类就是window
。
相关知识
在Qt中,每个QObject内部都有用来保存所有的子对象列表(children),同时还会保存自己的父对象(parent)。当它自己析构时,它会将自己从父对象(parent)的列表中删除,并且析构掉所有的子对象列表(children)。
看Qt源码理解半自动内存管理