找回密码
 立即注册
Qt开源社区 门户 查看内容

QT QPointer 解析

2019-8-21 10:33| 发布者: admin| 查看: 1301| 评论: 0

摘要: QPointer类是一个模板类,是为了QObject提供的一种监视指针。先来看一下普通C++与QPointer指针声明方式有什么不同。 普通C++指针声明方式: T* p1; QPointer指针声明方式:QPointer T p2; 它们的最大不同就是: ...
     QPointer类是一个模板类,是为了QObject提供的一种监视指针。先来看一下普通C++与QPointer指针声明方式有什么不同。

    普通C++指针声明方式:  T* p1;

    QPointer指针声明方式:QPointer <T> p2;

    它们的最大不同就是:

    当QPointer p2 指针引用的对象被销毁时候,p2指针会自动指向NULL,

    而p1的引用对象如果被销毁,p1则不会自动指向NULL,而是会变成野指针。

解释一下就是当p1引用别的对象A,而这个对象A在别的地方可能一不小心被销毁了,而p1还在指向这块内存,p1的值是没有变的,可是p1指向的这块内存已经不是以前的对象A了,这时候再调用p1就相当于变成了野指针,操作的时候会引起不可预测的风险。这时候QPointer指针就会变得很有用,当p2指向的对象销毁了,p2会自动指向NULL,而不会变成野指针。

我们来看下一段代码

    QList <QWidget*> listA;

    QList <QWidget*> listB;

    QWidget *w1 = new QWidget;

    QWidget *w2 = new QWidget;

    QWidget *w3 = new QWidget;

    listA.append(w1);

    listA.append(w2);

    listA.append(w3);

    listB.append(w1);

    listB.append(w2);

    listB.append(w3);

    foreach (QWidget *w, listA)

    {

        if(w)

        {

            listA.removeOne(w);

            delete w;

            w = NULL;

            qDebug() << "listA is not null";

        }

        else

            qDebug() << "listA is null";

    }

    foreach (QWidget *w, listB)

    {

        if(w)

        {

            qDebug() << "listB is not null";

        }

        else

            qDebug() << "listB is null";

    }

    这时候我们来猜测一下结果,第一个foreach的时候,判断如果listA里的成员指向不为空,就删除此成员,并置为空,所以前三句应该都是“listA is not null”;

    重点来看第二个foreach,来判断listB中的成员指向是否为空,到此为止,listB中的值始终是没有变得,也就是它里面的指针不为空,所以打印出来的应该是"listB is not null" 才对。结果是怎样的呢?

    那么怎样避免这种情况呢,QPointer的作用就出现了。我们来变换一下刚才的代码:

    QList <QPointer<QWidget>> listA;

    QList <QPointer<QWidget>> listB;

    QPointer<QWidget> w1 = new QWidget;

    QPointer<QWidget> w2 = new QWidget;

    QPointer<QWidget> w3 = new QWidget;

    listA.append(w1);

    listA.append(w2);

    listA.append(w3);

    listB.append(w1);

    listB.append(w2);

    listB.append(w3);

    foreach (QPointer<QWidget> w, listA)

    {

        if(w)

        {

            listA.removeOne(w);

            delete w;

            w = NULL;

            qDebug() << "listA is not null";

        }

        else

            qDebug() << "listA is null";

    }

    foreach (QPointer<QWidget> w, listB)

    {

        if(w)

        {

            qDebug() << "listB is not null";

        }

        else

            qDebug() << "listB is null";

    }

那么结果会是怎样的呢?

    我们发现了,使用了QPointer之后,对于第一个foreach结果是没变化的,当到第二个foreach的时候,listB就算里面的内容没有边,依然能判断出来listB中的成员自动都指向了NULL,这就是QPointer的最大作用!

重构:

    重构原则

    重构原则二

    如何重构(一)

设计原则:

    设计模式之七大设计原则

创建型设计模式:

    设计模式之单例模式

    设计模式之工厂模式

    设计模式之原型模式

    设计模式之建造者模式

结构型设计模式:

    设计模式之桥接模式

    设计模式之适配器模式

    设计模式之外观模式

    设计模式之组合模式

    设计模式之代理模式

    设计模式之享元模式

     

 行为型设计模式:

    设计模式之观察者模式  

    设计模式之策略模式

    设计模式之模板模式


----------------------------------------------------------------------------------------------------------------------
我们尊重原创,也注重分享,文章来源于微信公众号:跟田老师学C++,建议关注公众号查看原文。如若侵权请联系qter@qter.org。
----------------------------------------------------------------------------------------------------------------------

鲜花

握手

雷人

路过

鸡蛋

公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了