【QT】对象树

一、QT对象树的概念

先来看一下 QObject 的构造函数:

img

通过帮助文档我们可以看到,QObject 的构造函数中会传入一个 Parent 父对象指针,children() 函数返回 QObjectList。即每一个 QObject 对象有且仅有一个父对象,但可以有很多个子对象。按照这种形式排列就会形成一个对象树的结构,最上层是父对象,下面是子对象,在再下面是孙子对象,以此类推。

那么Qt为什么要这么设计呢?或者说这样设计的好处是什么呢?很简单,就是为了方便内存管理。我们在创建 QObject 对象时,提供一个父对象,那么我们创建的这个 QObject 对象会自动添加到其父对象的 children() 列表。当父对象析构的时候,这个子对象列表中的所有对象都会被析构,当析构子对象的时候,会自动从父对象的子对象列表中删除

这种机制在 GUI 程序开发过程中是相当实用的。有一个很明显的现象就是我们会在窗口中new很多控件,但是却没有delete,因为在父控件销毁时这些子控件以及布局管理器对象会一并销毁。

值得注意的是,如果在构造时设置父对象为 NULL,那么当前实例不会有父对象存在,Qt 也不会自动析构该实例,除非实例超出作用域导致析构函数被调用,或者用户在恰当时机使用 delete 操作符或者使用 deleteLater 方法。


在这里插入图片描述


QWidget

QWidget 也是 QObject 的子类,所以在 parent 机制上是没有区别的。然而实际使用时,对于 QWidget 和其派生类来说,在内存管理上要稍微复杂一些。因为 QWidget 需要和 QEventLoop 高度配合才能完成工作,我们举个例子来说明一下。

例如 QWidget 的关闭流程,首先用户点击关闭按钮触发 close() 槽,然后Qt向 widget 发送 QCloseEvent,默认的 QCloseEvent 会将 widget 隐藏起来,也就是hide()。我们可以看到,widget 的关闭实际是将其隐藏,而没有释放内存,虽然我们有时会重写 closeEvent 但也不会手动释放 widget。

所以需要设置 Qt::WA_DeleteOnClose 属性,那么会在 close 之后接着调用 widget 的析构函数,或者手动 delete。




二、对象树模型存在的小问题

示例代码1:

#include <QApplication>
#include <QPushButton>int main(int argc, char *argv[])
{QApplication a(argc, argv);QPushButton btn("button");QWidget w;btn.setParent(&w);w.show();return a.exec();
}

运行结果: 关闭 widget 后程序崩溃,没有正常结束

程序异常结束。

原因:

btn.setParent(&w);

btn对象,通过setParent()函数,将自己挂到对象树上。当程序结束时,根据栈区的特性,应该是先析构父对象–w,再析构btn可是由于Qt中的对象树自动析构原理,我们析构父对象会自动析构子对象。也就是说,在析构父对象–w时,会自动调用子对象btn的析构函数。然后,栈区继续销毁,按照顺序还要再一次析构btn。但是这时候已经是第二次调用 子对象的析构函数了,C++中不允许调用两次析构函数,因此,程序会崩溃。


在这里插入图片描述




三、正确写法–尽量在堆上创建子对象

示例代码2:

#include <QApplication>
#include <QPushButton>int main(int argc, char *argv[])
{QApplication a(argc, argv);QPushButton *btn = new QPushButton ("button");QWidget *w = new QWidget;btn->setParent(w);w->show();return a.exec();
}

w和btn被分配在堆上。w析构时,不会影响在栈区中的对象,程序正常运行。


由此我们可以看到,Qt 的对象树机制虽然在内存管理上很方便,但是也会带来一些麻烦,为了避免这些麻烦我们可以这么做:

  1. 先创建父对象再创建子类对象,并且在创建子对象时就指定父对象;
  2. 尽量在堆上创建子对象;



参考链接:

Qt 对象树

Qt中的内存泄漏

[Qt源码阅读(三) 对象树管理]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/171558.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何集成验证码短信API到你的应用程序

引言 当你需要为你的应用程序增加安全性和用户验证功能时&#xff0c;集成验证码短信API是一个明智的选择。验证码短信API可以帮助你轻松实现用户验证、密码重置和账户恢复等功能&#xff0c;提高用户体验并增强应用程序的安全性。本文将介绍如何将验证码短信API集成到你的应用…

什么c++流行造轮子而不是调包侠?

什么c流行造轮子而不是调包侠&#xff1f; 因为在c&#xff08;和c&#xff09;中&#xff0c;你造的轮子是真的可以跟官方的轮子拼性能的&#xff0c;只要你的算法足够优秀&#xff0c;实现足够小心。 最近很多小伙伴找我&#xff0c;说想要一些c资料&#xff0c;然后我根据自…

在windows服务器上部署一个单机项目以及前后端分离项目

目录 一. 单机项目在windows服务器上的部署 1.1 在本机上测试项目无误 1.1.1 在数据库中测试sql文件没问题 1.1.2 在tomcat中测试war文件无误 1.1.3 测试完成后&#xff0c;进入浏览器运行单机项目确保无误 1.2 在windows服务器中运行项目 二. 前后端分离项目在服务器上…

【工具使用】使用Audition增加增益的方法

一&#xff0c;简介 本文主要介绍如何在Adobe Audition 2020中改变波形的幅值。供参考。 二&#xff0c;操作方法 这里使用1KHz&#xff0c;-120dB信号为例。 2.1 方法一&#xff1a;直接使用悬浮窗口 窗口中输入6&#xff0c;波形的幅值就变成了-114dB。 注意&#xff1a…

鸿蒙ArkUI-X跨端应用开发,一套代码构建多平台应用

文章目录 一、项目介绍二、技术架构三、Gitee仓库地址四、ArkUI-X开发者文档五、快速开始——环境准备1、下载DevEco Studio&#xff0c;版本V4.0 Beta2以上2、打开DevEco&#xff0c;下载相关环境配置3、配置开发环境3.1、OpenHarmony SDK3.2、安装ArkUI-X SDK3.2、Android SD…

IDEA 断点高阶

一、按钮介绍 1.1 补充 返回断点处&#xff1a; 设置debug配置&#xff1a; 二、增加/切换debugger视图 三、window快捷键 所在行处&#xff1a; CtrlF8断点属性编辑&#xff1a; CtrlShiftF8 四、一些常用的高级功能 4.1 查看对象内存-Attach memory agent 1.勾选Atta…

Redis(04)| 数据结构-压缩列表

压缩列表的最大特点&#xff0c;就是它被设计成一种内存紧凑型的数据结构&#xff0c;占用一块连续的内存空间&#xff0c;不仅可以利用 CPU 缓存&#xff0c;而且会针对不同长度的数据&#xff0c;进行相应编码&#xff0c;这种方法可以有效地节省内存开销。 但是&#xff0c;…

微信小程序如何使用地球半径计算两组经纬度点之间的距离(自身位置与接口返回位置)【上】

目录 1.配置位置权限 2.获取当前自身经纬度 3. 请求接口拿到返回经纬 4. 循环取每一项的经纬 5.如何判断是否打开了定位权限 6.进行距离计算操作 7.运行效果 8.完整代码 首先在使用小程序时&#xff0c;请求的接口一定要去配置合法域名&#xff0c;才能够进行接下来…

【httpd】 Apache http服务器目录显示不全解决

文章目录 1. 文件名过长问题1.1 在centos中文件所谓位置etc/httpd/conf.d/httpd-autoindex.conf1.2 在配置文件httpd-autoindex.conf中的修改&#xff1a;1.3 修改完成后重启Apache&#xff1a; 1. 文件名过长问题 1.1 在centos中文件所谓位置etc/httpd/conf.d/httpd-autoindex…

cola架构:cola源码中访问者模式应用浅析

目录 1.访问者模式简介 2.cola访问者模式应用 2.1 cola被访问者类图 2.2 cola访问者类图 我们知道&#xff0c;如果一个对象结构包含很多类型的对象&#xff0c;希望对这些对象实施一些依赖其具体类型的操作&#xff0c;但又避免让这些操作“污染”这些对象的类&#xff0c…

竞赛 深度学习卫星遥感图像检测与识别 -opencv python 目标检测

文章目录 0 前言1 课题背景2 实现效果3 Yolov5算法4 数据处理和训练5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **深度学习卫星遥感图像检测与识别 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐…

基于Canal同步MySQL数据到Elasticsearch

基于Canal同步MySQL数据到Elasticsearch 基于 canal 同步 mysql 的数据到 elasticsearch 中。 1、canal-server 相关软件的安装请参考&#xff1a;《Canal实现数据同步》 1.1 pom依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmln…

c++多线程

目录 一、进程与线程 二、多线程的实现 2.1 C中创建多线程的方法 2.2 join() 、 detach() 和 joinable() 2.2.1 join() 2.2.2 detach() 2.2.3 joinable() 2.3 this_thread 三、同步机制&#xff08;同步原语&#xff09; 3.1 同步与互斥 3.2 互斥锁&#xff08;mu…

面向对象(类/继承/封装/多态)详解

简介: 面向对象编程&#xff08;Object-Oriented Programming&#xff0c;OOP&#xff09;是一种广泛应用于软件开发的编程范式。它基于一系列核心概念&#xff0c;包括类、继承、封装和多态。在这篇详细的解释中&#xff0c;我们将探讨这些概念&#xff0c;并说明它们如何在P…

【QT开发(17)】2023-QT 5.14.2实现Android开发

1、简介 搭建Qt For Android开发环境需要安装的软件有&#xff1a; JAVA SDK &#xff08;jdk 有apt install 安装&#xff09; Android SDK Android NDKQT官网的介绍&#xff1a; Different Qt versions depend on different NDK versions, as listed below: Qt versionNDK…

Hbase基本使用,读写原理,性能优化学习

文章目录 HBase简介HBase定义HBase数据模型**HBase** **逻辑结构****HBase** **物理存储结构****HBase** **基本架构** HBase 入门**HBase** **安装部署****HBase** 配置文件**HBase** 启动停止**HBase** **访问页面****HBase** **高可用****HBase Shell****HBase API**HBaseCo…

Java关于实例对象调用静态变量和静态方法问题

直接去看原文 原文链接:Java关于实例对象调用静态变量和静态方法问题_java对象可以调用static方法吗_骑个小蜗牛的博客-CSDN博客 --------------------------------------------------------------------------------------------------------------------------------- 实例…

ES6初步了解迭代器

迭代器是什么&#xff1f; 迭代器(iterator)是一种接口&#xff0c;为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 iterator 接口&#xff0c;就可以完成遍历操作 ES6创造了一种新的遍历方法for…of循环&#xff0c;iterator 接口主要供 for…of 使用 原生中具…

NIO和BIO编程

一、网络通信编程基本常识 1、什么是Socket&#xff1f; Socket是应用层与TCP/IP协议族通信的中间软件抽象层&#xff0c;它是一组接口&#xff0c;一般由操作系统提供。 2、短连接 短连接是指socket建立连接之后传输数据确定接收完后关闭连接 3、长连接 长连接是指建立so…

Go RESTful API 接口开发

文章目录 什么是 RESTful APIGo 流行 Web 框架-GinGo HelloWorldGin 路由和控制器Gin 处理请求参数生成 HTTP 请求响应Gin 的学习内容实战用 Gin 框架开发 RESTful APIOAuth 2.0接口了解用 Go 开发 OAuth2.0 接口示例 编程有一个准则——Don‘t Repeat Yourself&#xff08;不要…