【QT】关于Qt::WA_DeleteOnClose的使用问题

网友投稿 349 2022-09-01

【QT】关于Qt::WA_DeleteOnClose的使用问题

今天在解决软件bug的过程中,注意到QT关于​​[slot] bool QWidget::close()​​有这样一段说明:

If the widget has the Qt::WA_DeleteOnClose flag, the widget is also deleted. A close events is delivered to the widget no matter if the widget is visible or not.

逆向思考,如果我的QWidget或继承于QWidget的派生类没有设置相关的flag:​​Qt::WA_DeleteOnClose​​,那么他是不会自动析构的。情况真是如此吗?

测试环境: macOS Mojave 10.14 Qt Creator 4.41 Qt 5.9.2 Clang 7.0 apple, 64 bits

场景一: 独立widget,没有flag Qt::WA_DeleteOnClose

widget.cpp

#include "widget.h"#include "ui_widget.h"#include Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget){ ui->setupUi(this);}Widget::~Widget(){ delete ui; qDebug() << "Widget::~Widget()";}void Widget::on_pushButton_clicked(){ close(); //output: Widget::~Widget()}

main.cpp

#include "widget.h"#include int main(int argc, char *argv[]){ QApplication a(argc, argv); Widget w; w.show(); return a.exec();}

widget.ui:

在这种情况下,不设置flag ​​QT::WA_DeleteOnClose​​​,我们依然可用通过函数链:​​Widget::on_pushButton_clicked​​​ => ​​Widget::close​​​ 来触发析构函数。 那么QT关于此flag的说明到底是什么意思呢?接着看下面的场景。

场景二: 自定义的widget作为其他widget的child widget,没有flag Qt::WA_DeleteOnClose

现在widget.ui文件设置成这样:

main.cpp

#include "widget.h"#include int main(int argc, char *argv[]){ QApplication a(argc, argv); QWidget parentW; parentW.show(); Widget w(&parentW); w.show(); setbuf( stdout, NULL ); return a.exec();}

qwidget.cpp

#include "widget.h"#include "ui_widget.h"#include Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget){ ui->setupUi(this); printf( "this: %p\n", this ); printf( "ui: %p\n", ui );}Widget::~Widget(){ delete ui; qDebug() << "Widget::~Widget()";}void Widget::on_pushButton_clicked(){ qDebug() << testAttribute( Qt::WA_DeleteOnClose ); close();}

一开始显示:

this: 0x7ffeed17e9e0ui: 0x7faaacd12c40false

析构函数没有被调用。

场景三: 自定义的widget作为其他widget的child widget,有flag Qt::WA_DeleteOnClose

在场景二的基础上,Widget的构造函数中加上:

setAttribute( Qt::WA_DeleteOnClose, true );

this: 0x7ffee5578a28ui: 0x7fc99ef14f70trueWidget::~Widget()The program has unexpectedly finished.The process was ended forcefully.

系统报错:​​error for object 0x7ffee5578a28: pointer being freed was not allocated​​​ 也就说,函数链:​​Widget::on_pushButton_clicked​​ => ​​Widget::close​​触发了一次析构函数,后面widget的对象又被析构了一次。 注意到我们的Widget对象在main.cpp中是分配到栈内存的,所以在main函数结束后,系统会尝试析构我们的Widget对象。 在qwidget.cpp我们能找到这样的语句:

8442 if (!that.isNull()) {8443 data.is_closing = 0;8444 if (q->testAttribute(Qt::WA_DeleteOnClose)) {8445 q->setAttribute(Qt::WA_DeleteOnClose, false);8446 q->deleteLater();8447 }8448 }8449 return true;8450 }

接着,将Widget对象从堆里申请内存,就不会存在多次释放内存的问题了。 main.cpp

Widget *w = new Widget(&parentW);w->show();

总结:Qt::WA_DeleteOnClose用于申请堆内存的QWidget对象,并有通过close方法释放内存的需求的场景。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:大闸蟹鲜美上市,如何不让营销套路横行?(大闸蟹怎么推广)
下一篇:【VTK】三角化3D物体的表面
相关文章

 发表评论

暂时没有评论,来抢沙发吧~