• Qt——智能指针实战


    前言

    智能指针的使用,对很多程序员来说,都算是比较高深的存在,但又老是感觉这是一个值得去掌握,且需要去掌握的东西,所以,这次下定决心,来掌握一下Qt的智能指针的使用,当然,最常用的肯定是QSharedPoint这个了,其他的应该也就是顺带着讲一讲,并且,普及一些知识,从而让自己的能力更上一层楼把。

    正文

    一、理论介绍

    1、QPointer

    QPointer是Qt提供的空安全的智能指针,它用于解决悬挂指针的问题。QPoint在对象被删除后,会自动被设置为nullptr,避免访问已经无效的对象,它类似于普通指针,但提供了一些安全检查。

    总结来说就是:

    当你创建一个对象,然后使用QPointer指向这个对象,若出现delete 了那个对象,但是未将那个对象置空的情况的话,判断的时候,直接判断QPointer对象,就可以知道到底是真的删除了那个对象,还是假的删除了。避免了悬挂指针的问题。

    QPoint 充当一个管家的角色,对真正的指针做好判断。

    2、QScopedPoint

    QScopedPoint 是Qt提供的独占式的智能指针,用于管理动态分配的对象,QScopedPoint 在超出作用域时,自动删除对象,确保对象在不再需要时,被正确释放。

    3、QSharedPoint

    QSharedPoint 是Qt提供的共享引用计数的指针,可用于管理动态分配的对象。它通过引用计数跟踪对象的引用次数,当引用次数归零时,会自动删除对象。可以通过多个QSharedPoint共享同一个对象,对象会在最后一个引用者释放它时,才会被删除。

    4、QWeakPoint

    QWeakPoint 是Qt提供的弱引用智能指针,用于解决循环引用的问题。QWeakPoint 可以引用由QSharedPoint管理的对象,但不会增加引用计数的次数。QWeakPoint需要转换成QSharedPoint才能访问对象,当引用计数为0时,访问会失败。

    二、实战演练

    1、QPoint

    MyClass.h

    #ifndef MYCLASS_H
    #define MYCLASS_H
    #include 
    #include 
    class MyClass : public QObject
    {
        Q_OBJECT
    
    public:
        MyClass(const QString& name): m_name(name)
        {
            qDebug() << "MyClass 构造函数,名称为:"<<m_name;
        }
    
        ~MyClass()
        {
            qDebug() << "MyClass 析构函数,名称为:"<<m_name;
        }
    
        QString getName() const {return m_name;}
    
    private:
        QString m_name;
    };
    
    #endif // MYCLASS_H
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    main.cpp

    #include 
    #include 
    #include 
    #include "MyClass.h"
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        MyClass *obj = new MyClass("test");
    
        QPointer<MyClass> myObject(obj);
    
        if (myObject)
        {
            qDebug() << "对象存在,名称为" << myObject->getName();
        }
        else
        {
            qDebug() << "对象不存在";
        }
    
        delete obj;
        if (myObject)
        {
            qDebug() << "对象存在,名称为" << myObject->getName();
        }
        else
        {
            qDebug() << "对象不存在";
        }
    
        return a.exec();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    2、QScopedPoint

    void MainWindow::TestQScopedPointer()
    {
        useResource();
        qDebug() << "useResource 函数执行完毕";
    }
    
    void MainWindow::useResource()
    {
        QScopedPointer<Resource> scopedResource(new Resource());;
        //执行一些操作,使用资源
        qDebug() << "---> 使用资源 ";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    QScopedPoint 在适当的时候,会自动调用析构函数释放资源。

    结果:

    Resource 构造函数
    ---> 使用资源 
    Resource 析构函数
    useResource 函数执行完毕
    
    • 1
    • 2
    • 3
    • 4

    3、QSharedPoint

    a、示例一
    #include 
    #include 
    #include 
    // 假设的图形对象类
    class GraphicObject {
    public:
        GraphicObject() { qDebug() << "GraphicObject created"; }
        ~GraphicObject() { qDebug() << "GraphicObject destroyed"; }
        // 具体的图形对象操作
    };
    // 文档对象类
    class Document {
    public:
        Document() { qDebug() << "Document created"; }
        ~Document() { qDebug() << "Document destroyed"; }
        // 添加图形对象到文档
        void addGraphicObject(QSharedPointer<GraphicObject> graphicObject) {
            graphicObjects.append(graphicObject);
        }
        // 具体的文档操作
    private:
        QList<QSharedPointer<GraphicObject>> graphicObjects;
    };
    int main() {
        // 使用 QSharedPointer 确保图形对象的自动释放
        QSharedPointer<GraphicObject> graphicObject(new GraphicObject);
        // 使用 QScopedPointer 确保文档对象的自动释放
        QScopedPointer<Document> document(new Document);
        // 将图形对象添加到文档
        document->addGraphicObject(graphicObject);
        // 注意:在这里,graphicObject 和 document 会在适当的时候自动释放
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    b、示例二
    #ifndef MYSHAREDCLASS_H
    #define MYSHAREDCLASS_H
    #include 
    #include 
    class MySharedClass : public QObject
    {
        Q_OBJECT
    
    public:
        MySharedClass(int value): m_iValue(value)
        {
            qDebug() << "MySharedClass 构造函数,值为:"<<m_iValue;
        }
    
        ~MySharedClass()
        {
            qDebug() << "MySharedClass 析构函数,值为:"<<m_iValue;
        }
    
        void setValue(int value)
        {
            m_iValue = value;
        }
    
        int getValue() const
        {
            return m_iValue;
        }
    
    private:
        QString m_name;
        int m_iValue;
    };
    #endif // MYSHAREDCLASS_H
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    void MainWindow::TestSharedPointer()
    {
        //先用一个智能指针指向一个对象
        QSharedPointer<MySharedClass> pointer1(new MySharedClass(10));
    
        {
            //通过复制构造函数 让引用+1
            QSharedPointer<MySharedClass> pointer2 = pointer1;
    
            qDebug() << "---> pointer1 的值:"<<pointer1->getValue();
            qDebug() << "---> pointer2 的值"<<pointer2->getValue();
    
            //实际上都是对同一个对象进行操作
            pointer2->setValue(20);
            qDebug() << "--->w pointer1 的值:"<<pointer1->getValue();
            qDebug() << "--->w pointer2 的值"<<pointer2->getValue();
        }
    
        qDebug() << "--->w pointer1 的值:"<<pointer1->getValue();
        //之后,智能指针超出作用域之后,会自动析构掉
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    4、QWeakPoint

    #ifndef MYWEAKCLASS_H
    #define MYWEAKCLASS_H
    
    #include 
    #include 
    #include 
    
    class ObjectB;
    
    class ObjectA
    {
    public:
        ObjectA(const QString& name) : m_name(name){}
        ~ObjectA()
        {
            qDebug() << "objectA 析构函数,名称为:"<<m_name;
        }
    
        void setObjectB(const QSharedPointer<ObjectB> &objectB)
        {
            m_objectB = objectB;
        }
    private:
        QString m_name;
        QWeakPointer<ObjectB> m_objectB;
    };
    
    class ObjectB
    {
    public:
        ObjectB(const QString& name): m_name(name){}
    
        ~ObjectB()
        {
            qDebug() << "Object 析构函数,名称为:"<<m_name;
        }
    
        void setObjectA(const QSharedPointer<ObjectA> &objectA)
        {
            m_objectA = objectA;
        }
    
    private:
        QString m_name;
        QSharedPointer<ObjectA> m_objectA;
    };
    
    #endif // MYWEAKCLASS_H
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    void MainWindow::TestWeakPointer()
    {
        QSharedPointer<ObjectA> objectA(new ObjectA("ObjectA"));
        QSharedPointer<ObjectB> objectB(new ObjectB("ObjectB"));
    
        objectA->setObjectB(objectB);
        objectB->setObjectA(objectA);
    
        qDebug() << "程序结束";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    END、总结的知识与问题

    参考

    1、[Qt杂谈8.浅谈Qt智能指针那些事](https://www.cnblogs.com/luoxiang/p/17927569.html)

  • 相关阅读:
    大学英语六级单词记录
    SpringMVC的拦截器和JSR303的使用
    移动软件开发四——高校新闻网
    为什么用二进制进行数据传输、二进制概述及移位运算和乘除的关系
    Anacode+YOLO识别图片
    抽象类和接口,你了解多少?
    学习C++第三课
    hive日常使用时忘记部分补充(不定时)
    学校项目培训之Carla仿真平台之Carla学习内容
    Java架构师信息系统构建
  • 原文地址:https://blog.csdn.net/qq_43211060/article/details/136754891