[图解]Qt的智能指针

本文通过一个悬垂指针引发的bug引入,详细介绍了Qt中的智能指针机制,包括QPointer、QSharedPointer、QWeakPointer和QScopedPointer等,讲解了它们的特性和使用场景,并分享了实践中应注意的要点和示例。
摘要由CSDN通过智能技术生成

代码中出现一个bug,最终发现是由于在某个特殊情况下出现了使用垂悬指针,造成了程序崩溃,进而学习了解了Qt的智能指针机制。

一、悬垂指针的问题

如图,有两个指针a和b指向同一片内存,如果删除其中一个指针a,再去使用指针b的话,程序会崩溃。因为指针b此时已经是一个垂悬指针(Dangling pointer)了,它指向的内存已经被释放不再有效。

3743a8ec45d127ae72f3c8d2270bab19.jpeg
垂悬指针

使用指针b之前先判断b是否为空,这个做法在这里是不起作用的。问题的本质是通过指针a去释放内存时,指针b没有同步地置为空。

假如指针b能随内存的释放而自动置为空就好了,这正是智能指针所要解决的问题。

二、Qt中的智能指针

Qt提供了若干种智能指针:QPointer、QSharedPointer、QWeakPointer、QScopedPointer、QScopedArrayPointer、QSharedDataPointer、QExplicitlySharedDataPointer。

注:1、笔者Qt版本为4.8; 2、下述示例代码中"Plot"为"QObject"类的子类。

1、QPointer
QPointer只用于QObject的实例。如果它指向的对象被销毁,它将自动置空。如图:

11fa521d86bd897fb7f6ce32eded414a.jpeg
QPointer

这是Qt体系下的专门用于QObject的智能指针。常见使用方法:

QPointer<Plot> a(new T());   	//构造
QPointer<Plot> a(b);		//构造
a.isNull();			//判空
a.data();			//返回裸指针

2、QSharedPointer & QWeakPointer

QSharedPointer是引用计数(强)指针,当所有强指针销毁时,实际对象才会销毁。

QWeakPointer是弱指针,可以持有对QSharedPointer的弱引用。它作为一个观察者,不会引起实际对象销毁,当对象销毁时会自动置空。

这两种指针同时都有以下3个成员:强引用计数strongRef,弱引用计数weakRef和数据data。

43bc67ebf558b34f9740ddc46a205ba2.jpeg
Qt引用计数指针

85a92ab08b11d165d768d546cdff9b1a.jpeg

baec436b25061f7f8ac10d5ce780144e.jpeg
QSharedPointer &amp;amp;amp;amp;amp; QWeakPointer

两种指针分别对应于C++中的std::shared_ptr和std::weak_ptr。常见使用方法:

//构造
QSharedPointer<Plot> a(new Plot()); 
QSharedPointer<Plot> b = a;
QWeakPointer<Plot> c = a;  //强指针构造弱指针
QWeakPointer<Plot> d(a);     
  
//使用
c.clear();	//清除
a.isNull();	//判空
a->func(...); 	//(按常规指针来使用 "->")
QSharedPointer<Plot> e = d.toStrongRef();   //弱指针转为强指针。注意,弱指针无法操纵数据,必须转为强指针
QWeakPointer<Plot> f = e.toWeakRef();//强指针显式转为弱指针
QSharedPointer<Plot> g = e.dynamicCast<T>();  //动态类型转换

3、QScopedPointer

QScopedPointer保证当当前范围消失时指向的对象将被删除。它拥有一个很好的名字,它向代码的阅读者传递了明确的信息:这个智能指针只能在本作用域里使用,不希望被转让,因为它的拷贝构造和赋值操作都是私有的。

相当于C++中的std::unique_ptr,实例代码:

func(){
     
    Plot* plot = new Plot();
    //QScopedPointer出作用域自动销毁内存
    QScopedPointer<Plot>qsp(plot);
    //plot没有内存泄漏
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值