Qt智能指针--QWeakPointer

138 篇文章 196 订阅

概述

前面我们说到的QSharedPointer是一个强引用类型的智能指针,而QWeakPointer是一个弱引用类型的智能指针,和C++中的weak_ptr功能是一样的。

QWeakPointer 是为配合 QSharedPointer 而引入的一种智能指针,它更像是 QSharedPointer 的一个助手(因为它不具有普通指针的行为,没有重载operator*和->)。它的最大作用在于协助 QSharedPointer 工作,像一个旁观者一样来观测资源的使用情况。

QWeakPointer

QWeakPointer不能用于直接取消引用指针,但它可用于验证指针是否已在另一个上下文中被删除。并且QWeakPointer对象只能通过QSharedPointer的赋值来创建。

需要注意的是,QWeakPointer不提供自动转换操作符来防止错误发生。即使QWeakPointer跟踪指针,也不应将其视为指针本身,因为它不能保证指向的对象保持有效。

说了那么多,QWeakPointer到底有什么用呢?
答案就是:解除循环引用。

在概述中我们说到,QWeakPointer 是为配合 QSharedPointer 而引入的一种智能指针。而什么叫循环引用,就是说:两个对象互相使用一个 QSharedPointer成员变量指向对方(你中有我,我中有你)。由于QSharedPointer是一个强引用的计数型指针,只有当引用数为0时,就会自动删除指针释放内存,但是如果循环引用,就会导致QSharedPointer指针的引用永远都不能为0,这时候就会导致内存无法释放。
所以QWeakPointer诞生了,它就是为了打破这种循环的。并且,在需要的时候变成QSharedPointer,在其他时候不干扰QSharedPointer的引用计数。它没有重载 * 和 -> 运算符,因此不可以直接通过 QWeakPointer 访问对象,典型的用法是通过 lock() 成员函数来获得 QSharedPointer,进而使用对象。

示例

首先,我们来看一个QSharedPointer循环使用的示例:

#include <QWidget>
#include <QDebug>
#include <QWeakPointer>
#include <QSharedPointer>

class Children;
class Parent
{
public:
    ~Parent(){
        qDebug() << __FUNCTION__;
    }
    QSharedPointer<Children> m_pChildren;
};
class Children
{
public:
    ~Children(){
        qDebug() << __FUNCTION__;
    }
    QSharedPointer<Parent> m_pParent;
};

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();

    void test();
};
#include "widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    test();
}

Widget::~Widget()
{
    qDebug() << __FUNCTION__;
}

void Widget::test()
{
    QSharedPointer<Parent> parent(new Parent());
    QSharedPointer<Children> children(new Children());

    if(parent && children){
        parent->m_pChildren = children;
        children->m_pParent = parent;
    }
}

在构造函数中调用test()函数,执行完过后应该会自动释放parent和children对象,但是由于相互引用,在退出之前,引用计数为2,退出之后引用计数还是1,所以导致不能自动释放,并且此时这两个对象再也无法访问到。运行过后发现并没有进入到Parent和Children的析构函数中。这就导致了内存泄漏。

那么该如何解决这个问题呢?
很简单,直接将上述代码两个类中的成员变量声明

QSharedPointer<Children> m_pChildren;

QSharedPointer<Parent> m_pParent;

改成

QWeakPointer<Children> m_pChildren;

QWeakPointer<Parent> m_pParent;

这时候再次运行,就会看到输出:

~Children
~Parent

这是因为在test()退出之前引用计数是1,函数退出之后就自动析构,这就解除了上面的循环引用。

参考:
https://blog.csdn.net/Tanswer_/article/details/79039617

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luoyayun361

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值