现在的位置: 首页 > 综合 > 正文

qt智能指针介绍

2013年06月16日 ⁄ 综合 ⁄ 共 5270字 ⁄ 字号 评论关闭

简介

Qt提供了很多智能指针,比较常见的有QPointer, QSharedDataPointer QSharedPointerQWeakPointerQScopedPointer

描述

QPointer (4.0)  已经过时,可以被QWeakPointer所替代,它不是线程安全的。

QSharedDataPointer (4.0) 提供对数据的COPY-ON-WRITE以及浅拷贝,提供对数据线程安

全的保护。(注:提供对数据的线程安全保护要结合QsharedData来完成),它是线程安全的。

QSharedPointer (4.5)   实现了引用计数的可共享资源的强类型指针,它是线程安全的。有着与std::auto_ptr类似的特性,而最大的区别在于它不能转让所有权而auto_ptr可以。

QWeakPointer (4.5)    实现了引用计数的可共享资源的弱类型指针,它是线程安全的。

QScopedPointer (4.6)   实现了非引用计数的独享资源的强类型指针,它是线程安全的。

strong pointer       在有它所指向的资源的所有权期间,永远不会放弃这个所有权。

weak pointer:在有它所指向的资源的所有权期间,允许外界释放其资源从而使其放弃这个所有权。

详解

QScopedPointer 与 std::unique_ptr

它们概念上应当是是一样的。下面不再区分:

这是一个很类似auto_ptr的智能指针,它包装了new操纵符在堆上分派的动态对象,包管动态创建的对象在任何时候可以被正确地删除。但它的所有权加倍严格,一旦获取了对象的经管权,你就无法再从它那边取回来。

无论QScopedPointer 还是 std::unique_ptr 都拥有一个很好的名字,它向代码的浏览者传递了明白的信息:这个智能指针只能在本感化域里应用,不能被转让。因为它的拷贝机关和赋值操纵都是私有的,这点我们可以对比QObject及其派生类的对象哈。

重视:因为拷贝机关和赋值操纵私有的,它也具有auto_ptr同样的“缺点”——不能用作容器的元素。

QSharedPointer 与 std::shared_ptr

QSharedPointer 与 std::shared_ptr 行动最接近原始指针,是最像指针的"智能指针",应用局限比前面的提到的更广。

QSharedPointer 与 QScopedPointer 一样包装了new操纵符在堆上分派的动态对象,但它实现的是引用计数型的智能指针 ,可以被自由地拷贝和赋值,在随便率性的处所共享它,当没有代码应用(引用计数为0)它时才删除被包装的动态分派的对象。shared_ptr也可以安然地放 到标准容器中,并弥补了std::auto_ptr 和 QScopedPointer 因为转移语义而不能把指针作为容器元素的缺点。

boost::shared_ptr的管理机制其实并不复杂,就是对所管理的对象进行了引用计数,当新增一个boost::shared_ptr就将该对象的引用计数加一;少一个boost::shared_ptr就将该对象的引用计数减一,如果该对象的引用计数为0的时候,说明没有任何指针对其管理,才调用delete释放其所占的内存。(参见实例二)

和前面介绍的boost::scoped_ptr相比,boost::shared_ptr可以共享对象的所有权,因此其使用范围基本上没有什么限制(还是有一些需要遵循的使用规则,下文中介绍),自然也可以使用在stl的容器中。另外它还是线程安全的,这点在多线程程序中也非常重要。

boost::shared_ptr的使用规则:

避免对shared_ptr所管理的对象的直接内存管理操作,以免造成该对象的重释放

shared_ptr并不能对循环引用的对象内存自动管理(这点是其它各种引用计数管理内存方式的通病)。

不要构造一个临时的shared_ptr作为函数的参数。

如下列代码则可能导致内存泄漏:

void test()

{

    foo(boost::shared_ptr<implementation>(new    implementation()),g());

}

正确的用法为:

void test()

{

    boost::shared_ptr<implementation> sp    (new implementation());

    foo(sp,g());

}

QWeakPointer 与 std::weak_ptr

强引用类型的QSharedPointer已经很是好用,为什么还要有弱引用的 QWeakPointer

QWeakPointer 是为共同 QSharedPointer 而引入的一种智能指针,它更像是 QSharedPointer 的一个助手(因为它不具有通俗指针的行动,没有重载operator*->)。它的最鸿文用在于协助 QSharedPointer 工作,像一个观察迟疑者一样来观测资料的应用景象。

weak_ptr 主如果为了避免强引用形成环状

Qt中,对于QObject及其派生类对象,QWeakPointer有特别处理惩罚。它可以作为QPointer的调换品

QSharedDataPointer

这是为共同 QSharedData 实现隐式共享(写时复制 copy-on-write))而供给的便利对象。

Qt中浩繁的类都应用了隐式共享技巧,比如QPixmapQByteArrayQString...。而我们为本身的类实现隐式共享也很简单,比如要实现一个 Employee类:
定义一个只含有一个数据成员(QSharedDataPointer<EmployeeData>) 的 Employee 
我们须要的所稀有据成员放置于派生自QSharedData的 EmployeeData类中。

QExplicitlySharedDataPointer

这是为共同 QSharedData 实现显式共享而供给的便利对象。

QExplicitlySharedDataPointer 和 QSharedDataPointer 很是类似,然则它禁用了写时复制功能。这使得我们创建的对象更像一个指针。

一个例子,接前面的Employee

 #include "employee.h"

 int main()  

{     

  Employee e11001, "Albrecht Durer";      

      Employee e2 = e1;      

e1.setName"Hans Holbein";  

}

写时复制技巧导致:e1e2有雷同的工号,但有不合名字。与我们等待的不合,显式共享可以解决这个题目,这也使得Employee本身更像一个指针。

实例解析

实例一

int main(int argc, char *argv[])     

{     

    QCoreApplication a(argc, argv);     

    //raw pointer     

    QString *p = new QString("hello");     

    //Implements non-reference-counted strong pointer     

    QScopedPointer<QString> pScopedPointer(new QString("Scoped"));     

    // Build error, can NOT be shared and reference-counted     

    //QScopedPointer<QString> pScopedPointerpScopedPointer2 = pScopedPointer;     

10     //Implements reference-counted strong sharing of pointers     

11     QSharedPointer<QString> pSmart(new QString("Smart"));     

12     QSharedPointer<QString> pSmart2;     

13     pSmart2 = QSharedPointer<QString>(new QString("smart 2"));     

14     QSharedPointer<QString> pSharedPoninter;     

15     // can be shared safely and reference-counted     

16     pSharedPoninter = pSmart;     

17     qDebug() << *(pSmart.data());     

18     qDebug() << *(pSmart2.data());     

19     qDebug() << *(pSharedPoninter.data());     

20     QTimer *timer = new QTimer();     

21     QWeakPointer<QTimer> pWeakPointer = timer;     

22     //Weak pointer's resources can be deleted from outside world     

23     delete timer;     

24     if (pWeakPointer.isNull())     

25     {     

26         qDebug() << "contained QObject has been deleted";     

27     }     

28 }   

实例二

#include <string>

#include <iostream>

#include <boost/shared_ptr.hpp>

class implementation

{

public:

    ~implementation() { std::cout <<"destroying implementation\n"; }

    void do_something() { std::cout << "did something\n"; }

};

void test()

{

    boost::shared_ptr<implementation> sp1(new implementation());

    std::cout<<"The Sample now has "<<sp1.use_count()<<" references\n";

    boost::shared_ptr<implementation> sp2 = sp1;

    std::cout<<"The Sample now has "<<sp2.use_count()<<" references\n"; 

    sp1.reset();

    std::cout<<"After Reset sp1. The Sample now has "<<sp2.use_count()<<" references\n";

    sp2.reset();

    std::cout<<"After Reset sp2.\n";

}

void main()

{

    test();

}

该程序的输出结果如下:

The Sample now has 1 references

The Sample now has 2 references

After Reset sp1. The Sample now has 1 references

destroying implementation

After Reset sp2.

可以看到,boost::shared_ptr指针sp1sp2同时拥有了implementation对象的访问权限,且当sp1sp2都释放对该对象的所有权时,其所管理的的对象的内存才被自动释放。在共享对象的访问权限同时,也实现了其内存的自动管理。

参考文献

http://mobile.51cto.com/symbian-272817.htm

http://www.mysjtu.com/page/M0/S670/670782.html

http://blog.csdn.net/lmh12506/article/details/8897015

http://blog.csdn.net/txb70780533/article/details/5385516

Qt助手

抱歉!评论已关闭.