首页 > 系统相关 >Qt 5——对象树及对象树容易出现的内存问题

Qt 5——对象树及对象树容易出现的内存问题

时间:2023-09-25 20:12:37浏览次数:52  
标签:quit Qt 对象 QObject window 析构 树及

对象模型(对象树)

 

在Qt中创建对象的时候会提供一个Parent对象指针,下面来解释这个parent到底是干什么的。

QObject是以对象树的形式组织起来的。

  • 当你创建一个QObject对象时,会看到QObject的构造函数接收一个QObject指针作为参数,这个参数就是 parent,也就是父对象指针。这相当于,在创建QObject对象时,可以提供一个其父对象,我们创建的这个QObject对象会自动添加到其父对象的children()列表。
  • 当父对象析构的时候,这个列表中的所有对象也会被析构。这种机制在 GUI 程序设计中相当有用。例如,一个按钮有一个QShortcut(快捷键)对象作为其子对象。当我们删除按钮的时候,这个快捷键理应被删除。这是合理的。

QWidget是能够在屏幕上显示的一切组件的父类。

  • QWidget继承自QObject,因此也继承了这种对象树关系。一个孩子自动地成为父组件的一个子组件。因此,它会显示在父组件的坐标系统中,被父组件的边界剪裁。例如,当用户关闭一个对话框的时候,应用程序将其删除,那么,我们希望属于这个对话框的按钮、图标等应该一起被删除。事实就是如此,因为这些都是对话框的子组件。
  • 当然,我们也可以自己删除子对象,它们会自动从其父对象列表中删除。比如,当我们删除了一个工具栏时,其所在的主窗口会自动将该工具栏从其子对象列表中删除,并且自动调整屏幕显示。

对象树与内存问题

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

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

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

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

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

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

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

转自:https://blog.51cto.com/yang/2894095

标签:quit,Qt,对象,QObject,window,析构,树及
From: https://www.cnblogs.com/vickylinj/p/17728756.html

相关文章

  • PyQt5
    PyQt5是一个用于创建图形用户界面(GUI)应用程序的Python库。它是Python编程语言与Qt应用程序框架的绑定,允许开发人员使用Python语言来创建跨平台的桌面应用程序。Qt是一个功能强大且广泛使用的C++库,用于开发图形界面和应用程序功能。以下是关于PyQt5的一些重要信息和功能:1.跨平台性......
  • 【C++】动态内存管理 ⑤ ( 基础数据类型数组 内存分析 | 类对象 内存分析 | malloc 分
    文章目录一、基础数据类型数组内存分析1、malloc分配内存delete释放内存2、new分配内存free释放内存二、类对象内存分析1、malloc分配内存delete释放内存2、new分配内存free释放内存博客总结:C语言中使用malloc分配的内存,使用free进行释放;C++语言中......
  • Qt 5.12.9 + VS 2019配置并实现与三菱Q系列PLC通讯(1)软件的安装
    本人最近配置了QT5.12.9+VS2019,并实现了与三菱Q系列PLC通讯并实现数据交互的基本功能,在这个对中间遇到的一些问题和过程进行文字说明,以后大家有用到相关功能的话可以避免一些不必要的问题~需要安装的软件有三个:QT5.12.9、VS2019、MXComponetS4.19QT安装首先是对......
  • execjs执行js出现window对象未定义时的解决
    参考:https://www.jianshu.com/p/b82def6b3abchttps://blog.csdn.net/xx117501/article/details/102804286......
  • Qt窗口和视口解析(转)
    目录坐标变换流程世界坐标、窗口坐标和设备坐标窗口和视口世界变换和窗口视口变换QWidget、QGraphicsItem、QGraphicsView绘图窗口与视口绘图测试 坐标变换流程  QPainter.drawRect(QRectF)绘制图形传入的是世界坐标,而后经过变换矩形变为窗口坐标,最后经过窗口-视......
  • 15,面向对象原型继承
    子类对象名.__proto__=父类对象名;varuse={name:'岳不群',age:123,ff:function(){console.log(this.name+'在跑步');}};varniao={fei:function(){console.log(this.name+'在飞');}};varliyu......
  • C#中使用Newtonsoft.Charp实现Json对象序列化与反序列化
    场景C#中使用Newtonsoft.Json实现对Json字符串的解析:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/105795048上面讲的对JSON字符串进行解析,实际就是JSON对象的反序列化。在与第三方进行交互时常需要封装对象,存储各种属性消息,然后将对象序列化为json字符串并进......
  • Qt/C++音视频开发56-udp推流和拉流/组播和单播推流
    一、前言之前已经实现了rtsp/rtmp推流,rtsp/rtmp/hls/flv/ws-flv/webrtc等拉流,这种一般都需要依赖一个独立的流媒体服务程序,有没有一种更便捷的方式不需要这种依赖,然后又能实现推拉流呢,当然有的那就是udpp推流,其中udp推流还可以是组播或者单播推流,组播一般会选择224.0.0.1这个地址......
  • python面向对象的三大特性:封装性、继承性、多态性
    python面向对象的三大特性:封装性、继承性、多态性一、python中的封装在python代码中,封装具有两层含义:①在把现实世界中的实体中的属性和方法写到类的里面的操作即为封装。classPerson(object):#封装属性#封装方法②封装可以为属性和方法添加私有权限(属性和方......
  • Java面向对象思想解析:如何编写出高质量的代码
    面向对象思想面向对象思想面向对象是一种符合人类思维习惯的编程思想。现实生活中存在各种形态不同的事物,这些事物之间存在着各种各样的联系。在程序中使用对象来映射现实中的事物,使用对象的关系来描述事物之间的联系,这种思想就是面向对象。提到面向对象,自然会想到面向过程,面向过程......