【QT表格-1】QStandardItem的堆内存释放需要单独delete,还是随QStandardItemModel的remove或clear自动销毁?

背景:

学习qt表格控制,写博文记录:

 【QT表格-1】QStandardItem的堆内存释放需要单独delete,还是随QStandardItemModel的remove或clear自动销毁?

【QT表格-2】QTableWidget单元格结束编辑操作endEditting_qtablewidget 单元格编辑事件

【QT表格-3】QTableWidget导入/导出excel通用代码,不需要安装office,不依赖任何多余环境,甚至不依赖编程语言

【QT表格-4】由QTableView/QTableWidget显示进度条和按钮,理解qt代理delegate用法

【QT表格-5】QTableView用代码设置选中状态

【QT表格-6】QTableWidget的currentCellChanged实现中途撤销

项目中我用到listview和tablewidget(grid),后面都要绑定一个model,再用item来对应每个显示元素。

每一个item都是new出来的,所以必然要有delete。尤其对于gird,这个量很大,如果真的造成泄漏会很严重。所以我尝试在合适的位置执行delete,因为我不确定remove或clear这样的语句是否能自动释放内存,qt的帮助没有直接具体说明。

所以,我一直想找个直接的方法来验证,我就是想直接看到new出来的空间大小,但试过sizeof和_msize都不可以。而我尝试的结果是,如果delete写在clear或者remove之后会报错,写在之前就没问题,但这不能直接就得出结论。不严谨。

于是看到了这个文章:

QStandardItemModel内存管理_OneSea的博客-CSDN博客参考资料[1]QT中树控件QTreeView开发实例https://blog.csdn.net/q1302182594/article/details/45438161从这篇文章中,以及推荐的资料中可知,有这样疑问的人不少。我认为主要是qt的帮助文档这方面没说透。看过这位朋友的文章,这就想明白了一些。大不了,在remove或clear之前合适的位置执行delete即可。但是,我还是想找到最直接的依据。

分析:

上文给出的资料中,看到这样一段:

From the docs for QStandardItemModel::setItem()

The model takes ownership of the item.

The items will definitely be destroyed when the model itself is destroyed. They probably will be destroyed earlier if you use clear() on the model but I have not verified that.

The model itself, in this situation, will definitely be destroyed when the the object "this" is destroyed unless you choose to do it yourself earlier. When you create a QObject with a parent, or set the parent directly or indirectly after creation, then the parent will delete it as part of parent's destruction. See the the article "Object Trees and Object Ownership" in Assistant and the detailed description section of the QObject docs.

大致意思是:

第一段:在qt文档的QStandardItemModel::setItem()部分提到:model会获得item的所有权。

第二段:质疑item堆内存的生命周期。

第三段:对QObject文档的分析。说一旦某个对象对销毁,它的子对象会连带被销毁。基于这个理论,以及model会获得item所有权的说法,可以推断出,item应该会随着model的销毁而销毁,而model又会随它的父级销毁。

以上全是依据qt文档的分析。至少提供了思路。下面我就根据qt的文档来证实。

依据:

首先按照文中所示查阅QObject说明:

QObjects organize themselves in object trees. When you create a QObject with another object as parent, the object will automatically add itself to the parent's children() list. The parent takes ownership of the object; i.e., it will automatically delete its children in its destructor. You can look for an object by name and optionally type using findChild() or findChildren().

这里是说take ownership是什么意思,所以结合之前提到的model与item的描述,item应该会作为model的子对象一同被销毁。

再看析构函数的说明:

QObject::QObject(QObject *parent = nullptr)

Constructs an object with parent object parent.

The parent of an object may be viewed as the object's owner. For instance, a dialog box is the parent of the OK and Cancel buttons it contains.

The destructor of a parent object destroys all child objects.

这是QObject构造函数的说明部分。最后一句很明确,父对象的析构函数将销毁所有子对象。

从这点应该重新认识一下parent属性对内存管理的作用。

所以为什么MoveToThread要求不可以有parent。这必须是啊。让一个对象的子对象跑在其它线程中?这不乱套了?c#里面为什么要ui中的控件线程安全,不能让子线程随意访问,如果必须更新它要用到异步回调。

所以当我们做个窗口的时候,你不用分别去delete每一个控件,它自己就执行了。但是当打开一个子窗口的时候,不要指望指定它的parent为当前窗口,试过就知道了,如果指定子窗口的parent为当前窗口,子窗口会像控件一样嵌套在当前窗口。

所以,由线程和窗口来加深对object的理解。然后延伸到model和item。

总结:

本质上,这是qt对象树的概念。只要是QObject派生的对象,都有setParent函数,都可以在setParent或者构造时指定parent。回想一下,每个ui类的构造函数,总有个parent = 0的默认参数,亦即,默认情况下,新建的对象是“根”,没有父节点。随便打开一个以“ui_*.h”文件,里面很清楚能看到,每一个部件构造时都指定了parent,所以,当窗口销毁时,内部不会泄漏。

因此,之前说的model和item问题,new model时,要指定parent,而后就是全自动回收,不会泄漏。

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值