OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4892|回复: 2

QT对象树概念的优缺点-(多次析构问题)

[复制链接]

27

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
380
金钱
380
注册时间
2018-11-20
在线时间
61 小时
发表于 2019-7-6 14:19:30 | 显示全部楼层 |阅读模式
QT对象树概念的优缺点-(多次析构问题)

Qt 引入对象树的概念,在一定程度上解决了内存问题。



当一个 QObject 对象在堆上创建的时候,Qt 会同时为其创建一个对象树。不过,对象树中对象的顺序是没有定义的。这意味着,销毁这些对象的顺序也是未定义的。Qt 保证的是,任何对象树中的 QObject 对象 delete 的时候,如果这个对象有 parent,则自动将其从 parent 的 children() 列表中删除;如果有孩子,则自动 delete 每一个孩子。Qt 保证没有 QObject 会被 delete 两次,这是由析构顺序决定的。



如果 QObject 在栈上创建,Qt 保持同样的行为。正常情况下,这也不会发生什么问题。来看下下面的代码片段:(按顺序创建对象)

  • {
  •     QWidget window;
  •     QPushButton quit("Quit", &window);
  • }

[color=rgb(51, 102, 153) !important]复制代码

作为父组件的 window 和作为子组件的 quit 都是 QObject 的子类(事实上,它们都是 QWidget 的子类,而 QWidget 是 QObject 的子类)。这段代码是正确的,quit 的析构函数不会被调用两次,因为标准 C++ (ISO/IEC 14882:2003)要求,局部对象的析构顺序应该按照其创建顺序的相反过程。因此,这段代码在超出作用域时,会先调用 quit 的析构函数,将其从父对象 window 的子对象列表中删除,然后才会再调用 window 的析构函数。



但是,如果我们使用下面的代码:(先创建子对象,然后创建父对象,逆序创建)

  • {
  •     QPushButton quit("Quit");
  •     QWidget window;
  •     quit.setParent(&window);
  • }

[color=rgb(51, 102, 153) !important]复制代码

情况又有所不同,析构顺序就有了问题。我们看到,在上面的代码中,作为父对象的 window 会首先被析构,因为它是最后一个创建的对象。在析构过程中,它会调用子对象列表中每一个对象的析构函数,也就是说, quit 此时就被析构了。然后,代码继续执行,在 window 析构之后,quit 也会被析构,因为 quit 也是一个局部变量,在超出作用域的时候当然也需要析构。但是,这时候已经是第二次调用 quit 的析构函数了,C++ 不允许调用两次析构函数,因此,程序崩溃了。



由此我们看到,Qt 的对象树机制虽然帮助我们在一定程度上解决了内存问题,但是也引入了一些值得注意的事情。这些细节在今后的开发过程中很可能时不时跳出来烦扰一下,所以,我们最好从开始就养成良好习惯,在 Qt 中,尽量在构造的时候就指定 parent 对象,并且大胆在堆上创建。


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

27

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
380
金钱
380
注册时间
2018-11-20
在线时间
61 小时
 楼主| 发表于 2019-7-6 14:22:25 | 显示全部楼层
该文章原创于Qter开源社区(www.qter.org),作者devbean,转载于Qt开源社区
回复 支持 反对

使用道具 举报

0

主题

131

帖子

0

精华

初级会员

Rank: 2

积分
175
金钱
175
注册时间
2019-7-1
在线时间
6 小时
发表于 2019-7-12 13:40:49 | 显示全部楼层
好帖子,收藏了
IIS7站长  http://www.iis7.com/
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 17:24

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表