還是老規矩,QScopedPointer概念性的東西我就不贅述了,網上百度一抓一大把。
這里主要用實際的例子來說明一下QScopedPointer這個智能指針中data()和take()的用法,這里面是有坑的。
我們先來說一下data()和take()分別表示的是什么意思?
首先你可以把QScopedPointer看成是一個容器。
take()接口的意思是從這個容器中將對象刪除,並返回之前放在這個容器中的對象或者數據,QScopedPointer不再擁有這個對象的指針。
data()接口的意思就是返回容器中的指針,QScopedPointer還是擁有這個對象的指針的。
這個take()感覺用起來有點像qt中隊列(queue)的取操作(dequeue)。
有一種情況我們需要考慮的,就是在函數中使用了QScopedPointer如果來避免野指針的情況,本篇文章主要就是解決這個問題。
實際的例子是這樣的,我先在.h中定義了一個單例模式的接口。
static ScreenWidget *Instance();
然后在.cpp文件中實現這個接口
QScopedPointer<ScreenWidget> ScreenWidget::self; ScreenWidget *ScreenWidget::Instance() { if (self.isNull()) { static QMutex mutex; QMutexLocker locker(&mutex); if (self.isNull()) { self.reset(new ScreenWidget); } } return self.data(); }
這里用的是data()。
在main.cpp文件中是如下使用方式。
ScreenWidget* p1 = ScreenWidget::Instance();
p1->showFullScreen();
這種情況程序會掛掉。

這里就是出現了野指針的問題,因為在函數中使用data(),在函數結束以后QScopedPointer會被釋放,QScopedPointer內的對象也會被釋放,那么p1就是一個野指針了。程序自然就崩潰了。
ScreenWidget::Instance()->showFullScreen();
如果程序改成以上的樣子程序就沒什么問題。不存在野指針的情況。
QScopedPointer<ScreenWidget> ScreenWidget::self; ScreenWidget *ScreenWidget::Instance() { if (self.isNull()) { static QMutex mutex; QMutexLocker locker(&mutex); if (self.isNull()) { self.reset(new ScreenWidget); } } return self.take(); }
如果將上一段代碼的返回值改成take()。
ScreenWidget* p1 = ScreenWidget::Instance();
p1->showFullScreen();
再次使用這種方式,程序沒有問題,因為take()接口在返回的時候QScopedPointer刪除了對象,但是也保留了對象的指針。p1就不會出現野指針的情況。
ScreenWidget::Instance()->showFullScreen();
如果換成這樣的形式,程序也沒有崩潰,因為沒有指針指向的情況沒有野指針存在。
