Qt 智慧型指標學習

2021-08-25 20:17:18 字數 3966 閱讀 5930

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

從 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++編譯器的支援程度,你可以選用:

如何翻譯呢?我不太清楚,保留英文吧。

guarded pointers使用:乙個guarded指標,qpointer,行為和常規的指標 t * 類似

特點:當其指向的物件(t必須是qobject及其派生類)被銷毀時,它會被自動置null.

用途:當你需要儲存其他人所擁有的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 智慧型指標學習

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

Qt 智慧型指標學習

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