Qt的智能指针们——Qt

前言

用c++语言开发的一个难点就是指针,但是指针又是最常用的。有时候开辟了一块内存,但是后续使用完忘记释放,这就造成内存的泄露。为了解决这种尴尬的情况,除了长点心:一个new对应一个delete;还有一个办法是使用智能指针。

这里我只稍微说下Qt的常用的智能指针们,和c++11的部分智能指针很像。如果对c++的智能指针很熟悉,这里看一眼就没问题了;若c++基础不扎实,我找了篇c++11智能指针详解,两者可以结合着看。

 

介绍和示例

智能指针是个类,主要用于管理在堆上分配的内存,它将普通的指针封装为一个栈对象。

QPointer Qt的指针

QPointer所指向的对象必须是QObject或其派生类对象。 因为其对象析构时会执行QObject的析构函数,进而执行QObjectPrivate::clearGuards(this);作用对象被销毁时,自动设置为NULL,这样就不会出现野指针误用的情况了。(注意:写"."和"->"所调用的成员变量是不同的,一个是QPointer对象本身,一个是QPointer指向的指针对象。)

还有就是QPointer是线程不安全的,注意使用场合。

#include <QCoreApplication>
#include <QObject>
#include<QDebug>
#include<QPointer>
#include<QSharedPointer>
#include<QScopedPointer>

class Student:public QObject
{
public:
    explicit Student(QObject* parent=nullptr) :QObject(parent)
    {
        qDebug()<<__FUNCTION__;
    }
    ~Student()
    {
        qDebug()<<__FUNCTION__;
    }
};
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QPointer<Student> pt=new Student;
    delete pt;
    qDebug()<<"pt.isNull():"<<pt.isNull()<<"\n";

    Student* pt2=new Student;
    delete pt2;
    if(pt2)
    {
        qDebug()<<"pt2 is not null";

    }
    pt2=NULL;


    return a.exec();
}

执行结果如下,可以看出若用QPointer释放后,指针直接为空,而普通的指针释放,则不是空,需手动置零。

 

QSharedPointer共享指针

与 C++中的std::shared_ptr其作用是一样的,是引用计数型的智能指针。使用QSharedPointer时不需要再时刻牢记delete对象以避免内存泄漏, 因为当QSharedPointer超出其作用域时将被销毁;若对象的引用计数为0时, 也将会销毁其封装或指向的对象。

还有一点:QSharedPointer 是线程安全的,因此即使有多个线程同时修改 QSharedPointer 对象也不需要加锁。虽然 QSharedPointer 是线程安全的,但是 QSharedPointer 指向的内存区域可不一定是线程安全的。所以多个线程同时修改 QSharedPointer 指向的数据时还要应该考虑加锁。

    QSharedPointer<Student> pt(new Student);
    QSharedPointer<Student> pt2=pt;

    qDebug()<<" pt.reset();";
    pt.reset();
    qDebug()<<"pt2.reset()";
    pt2.reset();

运行结果如下,可以看出当两个共享指针都不再引用此对象时,被封装的对象被自动释放。

 

QScopedPointer作用域指针


QScopedPointer和C++中的智能指针std::unique_ptr其概念是一样的,它包装了new操作符在堆上分配的动态对象,能够保证动态创建的对象在任何时候都可以被正确地删除。

QScopedPointer拥有指针的管理权,出了作用域将自动释放删除。 注意这里并不会检查这个对象是否应该删除, 或者是否有其他指针依然引用/指向这个对象, 而是直接删除它.。这也是QScopedPointer和QSharedPointer在自动销毁对象这一作用上的区别。

void test()
{
    QScopedPointer<Student> pt(new Student);
}
Student* takeData()
{
    QScopedPointer<Student> pt(new Student);
    qDebug()<<pt.data();
    return pt.take();
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    //超出作用域,释放
    test();

    //转让管理权
    QScopedPointer<Student> pt(takeData());
    qDebug()<<pt.data();
    pt->sayHello();


    return a.exec();
}

 运行结果如下,以下演示了超出作用域后的释放,和转移管理权的示例,注意QScopedPointer::data虽然将对象指针给出去了,但是管理权还在QScopedPointer身上。

 

数组QScopedArrayPointer

因为QScopedPointer的拷贝构造和赋值操作私有的,所以不能用作容器的元素。所以就有了QScopedArrayPointer。这个用法很简单不说了,麻烦。

 

结束语

c++基础没打好,现在看到一点知识,进行一点学习,加油吧,少年!!

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值