很簡單的入門程式,應該比較熟悉吧 ^_^
在 從 qt 的 delete 說開來 一文中,我們提到這個程式存在記憶體洩露(表現就是析構函式不被呼叫),而且當時給出了三種解決方法:
注:本文中,我們從智慧型指標(smart pointer)角度繼續考慮這個問題
為了管理記憶體等資源,c++程式設計師通常採用raii(resource acquisition is initialization)機制:在類的建構函式中申請資源,然後使用,最後在析構函式中釋放資源。
如果沒有智慧型指標,程式設計師必須保證new物件能在正確的時機delete,四處編寫異常捕獲**以釋放資源,而智慧型指標則可以在退出作用域時(不管是正常流程離開或是因異常離開)總呼叫delete來析構在堆上動態分配的物件。
我們看看qt家族的智慧型指標:
智慧型指標
引入
qpointer
qt object 模型的特性(之一)
注意:析構時不會delete它管理的資源
qsharedpointer
帶引用計數
qt4.5
qweakpointer
qt4.5
qscopedpointer
qt4.6
qscopedarraypointer
qscopedpointer的派生類
qt4.6
qshareddatapointer
用來實現qt的隱式共享(implicit sharing)
qt4.0
qexplicitlyshareddatapointer
顯式共享
qt4.4
std::auto_ptr
std::shared_ptr
std::tr1::shared_ptr
c++0x
std::weak_ptr
std::tr1::weak_ptr
c++0x
std::unique_ptr
boost::scoped_ptr
c++0x
注:有了這些東西,我們就可以很容易改造我們前面的例子了(只需改變一行):
std::auto_ptrlabel(new qlabel("hello dbzhang800!"));根據你所用的qt的版本,以及c++編譯器的支援程度,你可以選用:
如何翻譯呢?我不太清楚,保留英文吧。
用途:當你需要儲存其他人所擁有的qobject物件的指標時,這點非常有用
乙個例子
qpointerlabel = new qlabel;如果在...部分你將該物件delete掉了,label會自動置null,而不會是乙個懸掛(dangling)的野指標。label->settext("&status:");
...if (label)
label->show();
qpointer 屬於qt object模型的核心機制之一,請注意和其他智慧型指標的區別。
這個沒多少要說的。
智慧型指標不能指向陣列(因為其實現中呼叫的是delete而非delete)
智慧型指標不能作為容器類的元素。
在c++0x中,auto_ptr已經不建議使用,以後應該會被其他3個智慧型指標所取代。
它們概念上應該是是一樣的。下面不再區分:
這是乙個很類似auto_ptr的智慧型指標,它包裝了new操作符在堆上分配的動態物件,能夠保證動態建立的物件在任何時候都可以被正確地刪除。但它的所有權更加嚴格,不能轉讓,一旦獲取了物件的管理權,你就無法再從它那裡取回來。
無論是qscopedpointer 還是 std::unique_ptr 都擁有乙個很好的名字,它向**的閱讀者傳遞了明確的資訊:這個智慧型指標只能在本作用域裡使用,不希望被轉讓。因為它的拷貝構造和賦值操作都是私有的,這點我們可以對比qobject及其派生類的物件哈。
用法(來自qt的manual):
考慮沒有智慧型指標的情況,
void myfunction(bool usesubclass)我們在異常處理語句中多次書寫delete語句,稍有不慎就會導致資源洩露。採用智慧型指標後,我們就可以將這些異常處理語句簡化了:try
catch (...)
delete p;
delete device;
}
void myfunction(bool usesubclass)另,我們一開始的例子,也是使用這兩個指標的最佳場合了(出main函式作用域就將其指向的物件銷毀)。
注意:因為拷貝構造和賦值操作私有的,它也具有auto_ptr同樣的「缺陷」——不能用作容器的元素。
qsharedpointer 與 std::shared_ptr 行為最接近原始指標,是最像指標的"智慧型指標",應用範圍比前面的提到的更廣。
qsharedpointer 與 qscopedpointer 一樣包裝了new操作符在堆上分配的動態物件,但它實現的是引用計數型的智慧型指標 ,可以被自由地拷貝和賦值,在任意的地方共享它,當沒有**使用(引用計數為0)它時才刪除被包裝的動態分配的物件。shared_ptr也可以安全地放到標準容器中,並彌補了std::auto_ptr 和 qscopedpointer 因為轉移語義而不能把指標作為容器元素的缺陷。
強引用型別的qsharedpointer已經非常好用,為什麼還要有弱引用的 qweakpointer?
qweakpointer 是為配合 qsharedpointer 而引入的一種智慧型指標,它更像是 qsharedpointer 的乙個助手(因為它不具有普通指標的行為,沒有過載operator*和->)。它的最大作用在於協助 qsharedpointer 工作,像乙個旁觀者一樣來觀測資源的使用情況。
在qt中,對於qobject及其派生類物件,qweakpointer有特殊處理。它可以作為qpointer的替代品
這是為配合 qshareddata 實現隱式共享(寫時複製 copy-on-write))而提供的便利工具。
qt中眾多的類都使用了隱式共享技術,比如qpixmap、qbytearray、qstring、...。而我們為自己的類實現隱式共享也很簡單,比如要實現乙個 employee類:
具體實現看 qshareddatapointer 的manual,此處略
這是為配合 qshareddata 實現顯式共享而提供的便利工具。
qexplicitlyshareddatapointer 和 qshareddatapointer 非常類似,但是它禁用了寫時複製功能。這使得我們建立的物件更像乙個指標。
乙個例子,接前面的employee:
#include "employee.h"寫時複製技術導致:e1和e2有相同的工號,但有不同名字。與我們期待的不同,顯式共享可以解決這個問題,這也使得employee本身更像乙個指標。int main()
先前竟未注意到官方的這兩篇文章(這是失敗):
便看看google編碼規範中對3個智慧型指標的建議:
scoped_ptr
auto_ptr
confusing and bug-prone ownership-transfer semantics. do not use.
shared_ptr
safe with const referents (i.e.shared_ptr
). reference-counted pointers with non-const referents can occasionally be the best design, but try to rewrite with single owners where possible.
Qt 智慧型指標學習
很簡單的入門程式,應該比較熟悉吧 從 qt 的 delete 說開來 一文中,我們提到這個程式存在記憶體洩露 表現就是析構函式不被呼叫 而且當時給出了三種解決方法 注 本文中,我們從智慧型指標 smart pointer 角度繼續考慮這個問題 為了管理記憶體等資源,c 程式設計師通常採用raii r...
Qt 智慧型指標學習
很簡單的入門程式,應該比較熟悉吧 從 qt 的 delete 說開來 一文中,我們提到這個程式存在記憶體洩露 表現就是析構函式不被呼叫 而且當時給出了三種解決方法 注 本文中,我們從智慧型指標 smart pointer 角度繼續考慮這個問題 為了管理記憶體等資源,c 程式設計師通常採用raii r...
Qt 智慧型指標學習
很簡單的入門程式,應該比較熟悉吧 從 qt 的 delete 說開來 一文中,我們提到這個程式存在記憶體洩露 表現就是析構函式不被呼叫 而且當時給出了三種解決方法 注 本文中,我們從智慧型指標 smart pointer 角度繼續考慮這個問題 為了管理記憶體等資源,c 程式設計師通常採用raii r...