如果没有智能指针,程序员必须保证new对象能在正确的时机delete,四处编写异常捕获代码以释放资源,而智能指针则可以在退出作用域时(不管是正常流程离开或是因异常离开)总调用delete来析构在堆上动态分配的对象。
来看看一个野指针例子
程序将会异常结束,因为delete view 后 label也被delete了
QPointer作为一个模板类,它有很类似与普通的指针,它会动态监视分配空间的对象是否被delete 了。它保存了一个QObject 的指针,并把这个指针的指针交给全局变量处理,在对象销毁时会调用 QObjectPrivate::clearGuards() 函数把双指针置为零,所以可以使用 QPointer::isNull() 判断是否已经被销毁。它不是线程安全的。该类在QT4被废弃了,但QT5又重写了
看看局部变量,当show函数结束时并没有堆widget删除,导致内存溢出
QSharedPointer 行为最接近原始指针,是最像指针的"智能指针", 与 QScopedPointer 一样包装了new操作符在堆上分配的动态对象,但它实现的是引用计数型的智能指针 ,可以被自由地拷贝和赋值,在任意的地方共享它,当没有代码使用(引用计数为0)它时才删除被包装的动态分配的对象。实现了引用计数的可共享资源的强类型指针,它是线程安全的。它不能转让所有权。运行后,widget界面将会一闪而过,因为它已经在show()作用域结束时被销毁了
QWeakPointer它实现了引用计数的可共享资源的弱类,它是线程安全的。在它所指向的资源的所有权期间,允许外界释放其资源从而使其放弃所有权,它更像是 QSharedPointer 的助手。在QT4它比QPointer更加高效,但是在QT5它被废弃啦,你不应该继续使用它
QScopedPointer实现了非引用计数的独享资源的强类型指针,它是线程安全的。它的所有权不能转让,因为它的拷贝和赋值都是私有的
QScopedArrayPointer派生自 QScopedPointer 它存储的是指向动态分配的对象指针,默认使用的是 delete [] 释放
QSharedDataPointer可以指向一个隐式共享类对象。QSharedDataPointer<T>你可以很容易的实现自己的隐式共享类,QSharedDataPointer实现了线程安全的引用计数,从而保证了你自己写的可重入的隐式共享类不会因为加入QSharedDataPointer而变得不可重入。隐式共享应用在很多Qt类中,实现了速率和内存效率的有效结合
EmployeeData 必需继承自QSharedData,QSharedData类是共享数据的基类,它提供引用计数,它只有默认的构造函数,拷贝构造函数和析构函数,一般情况下,我们有必要自己重写这几个函数。Employee数据成员只有一个QSharedDataPointer<EmployeeData>指针,所以对d访问必须通过->方法。当我们需要改变d的数据时,如果d的引用计数大于1的话,将会调用detach()对d进行拷贝生成新的对象。从而保证了所以对d的改变,不会影响到别的引用。Employee对象被拷贝、用于赋值或者当成参数传递时,QSharedDataPointer指针的引用技术自动增加1;Employee对象被销毁或者超出作用域时,QSharedDataPointer指针的引用计数将自动减小1.当QSharedDataPointer引用计数为0时将自动销毁。
它是深拷贝的
自动垃圾回收
t 对象清理器是实现自动垃圾回收的很重要的一部分。QObjectCleanupHandler可以注册很多子对象,并在自己删除的时候自动删除所有子对象。同时,它也可以识别出是否有子对象被删 除,从而将其从它的子对象列表中删除。这个类可以用于不在同一层次中的类的清理操作,例如,当按钮按下时需要关闭很多窗口,由于窗口的 parent 属性不可能设置为别的窗口的 button,此时使用这个类就会相当方便。