Qt智慧型指標

2021-06-27 15:27:08 字數 3851 閱讀 8317

**:

很簡單的入門程式,應該比較熟悉吧 ^_^

在  從 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;

label->settext("&status:");

...if (label)

label->show();

如果在...部分你將該物件delete掉了,label會自動置null,而不會是乙個懸掛(dangling)的野指標。

qpointer 屬於qt object模型的核心機制之一,請注意和其他智慧型指標的區別。

這個沒多少要說的。

智慧型指標不能指向陣列(因為其實現中呼叫的是delete而非delete)

智慧型指標不能作為容器類的元素。

在c++0x中,auto_ptr已經不建議使用,以後應該會被其他3個智慧型指標所取代。

它們概念上應該是是一樣的。下面不再區分:

這是乙個很類似auto_ptr的智慧型指標,它包裝了new操作符在堆上分配的動態物件,能夠保證動態建立的物件在任何時候都可以被正確地刪除。但它的所有權更加嚴格,不能轉讓,一旦獲取了物件的管理權,你就無法再從它那裡取回來。

無論是qscopedpointer 還是 std::unique_ptr 都擁有乙個很好的名字,它向**的閱讀者傳遞了明確的資訊:這個智慧型指標只能在本作用域裡使用,不希望被轉讓。因為它的拷貝構造和賦值操作都是私有的,這點我們可以對比qobject及其派生類的物件哈。

用法(來自qt的manual):

考慮沒有智慧型指標的情況,

void myfunction(bool usesubclass)

try

catch (...)

delete p;

delete device;

}

我們在異常處理語句中多次書寫delete語句,稍有不慎就會導致資源洩露。採用智慧型指標後,我們就可以將這些異常處理語句簡化了:

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"

int main()

寫時複製技術導致:e1和e2有相同的工號,但有不同名字。與我們期待的不同,顯式共享可以解決這個問題,這也使得employee本身更像乙個指標。

先前竟未注意到官方的這兩篇文章(這是失敗):

便看看google編碼規範中對3個智慧型指標的建議:

scoped_ptrauto_ptrconfusing and bug-prone ownership-transfer semantics. do not use.

shared_ptrsafe 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 智慧型指標例項

myclass const myclass rhs str rhs.str myclass operator const myclass rhs myclass qstring str int main int argc,char argv qdebug test qsharedptr qshare...

Qt 智慧型指標學習

很簡單的入門程式,應該比較熟悉吧 在 從 qt 的 delete 說開來 一文中,我們提到這個程式存在記憶體洩露 表現就是析構函式不被呼叫 而且當時給出了三種解決方法 注 本文中,我們從智慧型指標 smart pointer 角度繼續考慮這個問題 為了管理記憶體等資源,c 程式設計師通常採用raii...