【QT入门】 Qt内存管理机制详解

往期回顾:

【QT入门】 Qt槽函数五种常用写法介绍-CSDN博客

【QT入门】 Qt实现自定义信号-CSDN博客

【QT入门】 Qt自定义信号后跨线程发送信号-CSDN博客

【QT入门】 Qt内存管理机制详解

Qt中的内存管理主要是通过对象树和智能指针来实现的,下面一一列举各类方法:

一、对象树(Object Tree):

1、什么是对象数:

Qt中的对象可以形成一个层次结构,其中一个对象可以拥有子对象。当父对象被销毁时,它会自动销毁其所有子对象。这种父子关系形成了对象树。

Qt里所有类的最终父类是QObject。

而在Qt的ui设计里,QWidget是所有ui组件最大的父对象。QWidget继承于QObject。

2、内存管理方式:

当一个对象被添加为另一个对象的子对象时,Qt会自动管理子对象的内存,确保在父对象被销毁时,子对象也会被正确地销毁,从而避免内存泄漏。

对比C++派生类的内存管理方式:

构造顺序:先执行基类的构造函数,再执行派生类的构造函数

析构顺序:先执行派生类的析构函数,再执行基类的析构函数。

也就是说,QObject及其派生类的对象,如果其parent非空,那么其parent析构时会析构该对象

QWidget及其派生类的对象。

我们也可以设置Qt:WA__DeleteOnClose标志位,当close时会调用QWidgetPrivate::close_ _helper,进而调用deleteLater析构该对象。

3、示例

在一个Qt应用程序中,有一个主窗口 MainWindow,该窗口包含了一个按钮 QPushButton 和一个文本框 QLineEdit。当创建按钮和文本框时,可以将它们的父对象设置为主窗口 MainWindow,这样当主窗口关闭时,按钮和文本框会自动被销毁,无需手动管理它们的内存。

#include <QtWidgets>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    
    QMainWindow mainWindow;
    
    QPushButton *button = new QPushButton("Click me", &mainWindow);
    QLineEdit *lineEdit = new QLineEdit(&mainWindow);
    
    mainWindow.show();
    
    return app.exec();
}

二、智能指针(Smart Pointers):

Qt提供了 QSharedPointer 和 QWeakPointer 来管理对象的生命周期,从而简化内存管理。

1、QSharedPointer:

QSharedPointer 允许多个指针共享同一个对象,并且会在最后一个指针超出作用域时自动销毁对象。

2、QWeakPointer :

用于解决潜在的循环引用问题,避免内存泄漏。

3、示例:

在一个Qt应用程序中,有一个数据模型类 DataModel,该类负责管理一些数据对象。可以使用 QSharedPointer 来管理数据对象的生命周期,确保在不再需要数据对象时能够正确地释放内存,同时允许多个地方共享对数据对象的引用。

#include <QtWidgets>

class DataModel
{
public:
    DataModel() {}
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    
    QSharedPointer<DataModel> dataModel(new DataModel());
    
    return app.exec();
}

三、信号槽机制:

1、为什么信号槽机制可以帮助管理内存:

因为Qt的信号槽机制可以用于对象之间的通信,而不需要直接引用对象的指针。这样就避免了内存管理问题,因为对象之间的连接是通过信号和槽进行的,而不是直接引用对象的指针。

2、示例:

在一个Qt应用程序中,有一个数据处理类 DataProcessor,该类负责处理数据并发出信号通知其他部分。其他部分可以通过连接信号和槽的方式来接收数据处理类发出的信号,而不需要直接引用数据处理类的指针,从而避免了可能的内存管理问题。

#include <QtWidgets>

class DataProcessor : public QObject
{
    Q_OBJECT
    
public slots:
    void processData()
    {
        qDebug() << "Processing data...";
        emit dataProcessed();
    }
    
signals:
    void dataProcessed();
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    
    DataProcessor processor;
    
    QObject::connect(&processor, &DataProcessor::dataProcessed, [](){
        qDebug() << "Data processed signal received!";
    });
    
    processor.processData();
    
    return app.exec();
}

四、代码示例

最后,用一个示例把几个方法综合起来看看:

#include <QtWidgets>

class CustomWidget : public QWidget
{
public:
    CustomWidget(QWidget *parent = nullptr) : QWidget(parent)
    {
        // 设置父对象,建立父子关系
        QPushButton *button = new QPushButton("Click me", this);
        
        // 使用智能指针管理对象生命周期
        QSharedPointer<QLineEdit> lineEdit(new QLineEdit(this));
        
        // 连接信号槽
        connect(button, &QPushButton::clicked, this, [lineEdit](){
            QString text = lineEdit->text();
            qDebug() << "Button clicked, LineEdit text: " << text;
        });
    }
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    
    // 创建主窗口作为对象树的根节点
    QMainWindow mainWindow;
    
    // 创建自定义小部件,设置其父对象为主窗口
    CustomWidget customWidget(&mainWindow);
    
    // 显示主窗口
    mainWindow.show();
    
    return app.exec();
}

1、代码内存管理分析:

|---------------------------------------------------------------|
| 1、CustomWidget 是一个自定义的小部件,它包含了一个按钮和一个文本框。 |
| 2、在 CustomWidget 的构造函数中,按钮和文本框的父对象都被设置为 CustomWidget,建立了父子关系。 |
| 3、使用 QSharedPointer 管理文本框对象的生命周期,确保在不再需要时能够正确释放内存。 |
| 4、通过信号与槽机制,按钮的点击事件与文本框文本的输出进行了连接,实现了对象之间的通信。 |


都看到这里了,点个赞再走呗朋友~

加油吧,预祝大家变得更强!

相关推荐
半盏茶香24 分钟前
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
c语言·开发语言·c++·算法
Evand J1 小时前
LOS/NLOS环境建模与三维TOA定位,MATLAB仿真程序,可自定义锚点数量和轨迹点长度
开发语言·matlab
LucianaiB1 小时前
探索CSDN博客数据:使用Python爬虫技术
开发语言·爬虫·python
Ronin3051 小时前
11.vector的介绍及模拟实现
开发语言·c++
计算机学长大白2 小时前
C中设计不允许继承的类的实现方法是什么?
c语言·开发语言
PieroPc3 小时前
Python 写的 智慧记 进销存 辅助 程序 导入导出 excel 可打印
开发语言·python·excel
2401_857439696 小时前
SSM 架构下 Vue 电脑测评系统:为电脑性能评估赋能
开发语言·php
SoraLuna6 小时前
「Mac畅玩鸿蒙与硬件47」UI互动应用篇24 - 虚拟音乐控制台
开发语言·macos·ui·华为·harmonyos
xlsw_6 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
Dream_Snowar7 小时前
速通Python 第三节
开发语言·python