Qt 中的智慧型指標之QSharedPointer

2021-09-25 10:00:21 字數 4181 閱讀 7482

c++11 標準中的有提供智慧型指標,在 qt 中也提供了類似的替代功能,並且比 c++11 標準中提供的功能還要強大,所以如果我們使用 qt 作為基礎庫,那麼就沒有必要使用c++11 的智慧型指標。

qt 的智慧型指標包括:

qsharedpointer

qscopedpointer

qscopedarraypointer

qweakpointer

qpointer

qshareddatapointer

qsharedpointer

qsharedpointer 大體相當於c++11 標準中的 shared_ptr,是在 qt 4.5 中引入的,所以只要我們的 qt 版本大於 qt 4.5 就可以使用這個類。

要使用這個智慧型指標類,首先要包含對應的標頭檔案:

#include

qsharedpointer 內部維持著對擁有的記憶體資源的引用計數。比如有 5個 qsharedpointer 擁有同乙個記憶體資源,那麼這個引用計數就是 5。這時如果乙個 qsharedpointer 離開了它的作用域,那麼就還剩下 4 個 qsharedpointer 擁有這個記憶體資源,引用計數就變為了 4。 當引用計數下降到 0 時,這個記憶體資源就被釋放了。

qsharedpointer 的建構函式有如下這幾種。

qsharedpointer();

qsharedpointer(x *ptr);

qsharedpointer(x *ptr, deleter deleter);

qsharedpointer(std::nullptr_t);

qsharedpointer(std::nullptr_t, deleter d);

qsharedpointer(const qsharedpointer&other);

qsharedpointer(const qweakpointer&other);

因此我們可以: 

構造乙個空的 qsharedpointer 

通過乙個普通指標來構造乙個 qsharedpointer 

用另乙個 qsharedpointer 來構造乙個 qsharedpointer 

用乙個 qweakpointer 來構造乙個 qsharedpointer

並且,我們可以指定 deleter。因此 qsharedpointer 也可以用於指向 new 分配的記憶體。

qsharedpointer 是執行緒安全的,因此即使有多個執行緒同時修改 qsharedpointer 物件也不需要加鎖。這裡要特別說明一下,雖然 qsharedpointer 是執行緒安全的,但是 qsharedpointer 指向的記憶體區域可不一定是執行緒安全的,所以多個執行緒同時修改 qsharedpointer 指向的資料時還要應該考慮加鎖的。

下面是個 qsharedpointer 的例子,演示了如何自定義 deleter。

static void dodeletelater(myobject *obj)

void otherfunction()

qsharedpointer 使用起來就像是普通的指標。唯一讓我不滿意的地方就是 qsharedpointer 不支援指向乙個陣列。

qscopedpointer

qscopedpointer 類似於 c++ 11 中的 unique_ptr。當我們的記憶體資料只在一處被使用,用完就可以安全的釋放時就可以使用 qscopedpointer。

比如下面的**:

void myfunction(bool usesubclass)

try  catch (...)

delete p;

delete device;

}如果用 qscopedpointer,就可以簡化為:

void myfunction(bool usesubclass)

qscopedarraypointer

如果我們指向的記憶體資料是乙個陣列,這時可以用 qscopedarraypointer。qscopedarraypointer 與 qscopedpointer 類似,用於簡單的場景。

例如下面這個例子:

void foo()

qpointer

qpointer 與其他的智慧型指標有很大的不同。其他的智慧型指標都是為了自動釋放記憶體資源而設計的。 qpointer 智慧型用於指向 qobject 及派生類的物件。當乙個 qobject 或派生類物件被刪除後,qpointer 能自動把其內部的指標設為 0。這樣我們在使用這個 qpointer 之前就可以判斷一下是否有效了。

為什麼非要是 qobject 或派生類呢,因為 qobject 可以構成乙個物件樹,當這顆物件樹的頂層物件被刪除時,它的子物件自動的被刪除。所以乙個 qobject 物件是否還存在,有時並不是那麼的明顯。有了 qpointer 我們在使用乙個物件之前,至少可以判斷一下。

要特別注意的是,當乙個 qpointer 物件超出作用域時,並不會刪除它指向的記憶體物件。這和其他的智慧型指標是不同的。

下面給乙個簡單的例子:

qpointerlabel = new qlabel;

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

...if (label)

label->show();

qshareddatapointer

qshareddatapointer 這個類是幫我們實現資料的隱式共享的。我們知道 qt 中大量的採用了隱式共享和寫時拷貝技術。比如下面這個例子:

qstring str1 = "abcdefg";

qstring str2 = str1;

qstring str2[2] = 'x';

第二行執行完後,str2 和 str1 指向的同一片記憶體資料。當第三句執行時,qt 會為 str2 的內部資料重新分配記憶體。這樣做的好處是可以有效的減少大片資料拷貝的次數,提高程式的執行效率。

qt 中隱式共享和寫時拷貝就是利用 qshareddatapointer 和 qshareddata 這兩個類來實現的。

比如我們有個類叫做 employee,裡面有些資料希望能夠利用隱式共享和寫時拷貝技術。那麼我們可以把需要隱式共享的資料封裝到另乙個類中,比如叫做 employeedata,這個類要繼承自 qshareddata。

class employeedata : public qshareddata

employeedata(const employeedata &other)

: qshareddata(other), id(other.id), name(other.name)

~employeedata()

int id;

qstring name;

};這個例子中,id 和 name 就是我們要隱式共享和寫時拷貝的資料。那麼 employee 類需要這麼來實現。

class employee

employee(const employee &other)

: d (other.d)

employee(int id, const qstring &name) 

employee(const employee &other)

: d (other.d)

void setid(int id)

void setname(const qstring &name)

int id() const

qstring name() const

private:

qshareddatapointerd;

};我們對 employee 中資料的訪問都要通過 d。那麼當需要修改 id 或 name 時,qshareddatapointer 類自動的呼叫 detach() 方法來完成資料的拷貝。d (other.d) 則完成了隱式共享的功能。

看到了吧,就這麼簡單。如果這些功能都要自己實現的話,**量可是不小的。

於這個類有關的還有個 qexplicitlyshareddatapointer 這個類用到的機會更少,所以就不多做介紹了,請大家自己看 qt 的幫助文件。

qweakpointer

最後來簡單介紹一下 qweakpointer。這個類用到的機會不多。(說實話我不太會用這個類,下面的介紹都是網上抄的.)

qweakpointer 是為配合 qsharedpointer 而引入的一種智慧型指標,它更像是 qsharedpointer 的乙個助手(因為它不具有普通指標的行為,沒有過載operator*和->)。它的最大作用在於協助 qsharedpointer 工作,像乙個旁觀者一樣來觀測資源的使用情況。

智慧型指標類模板(中) Qt中的智慧型指標

qt中的智慧型指標 qpointer 當其指向的物件被銷毀時,它會被自動置空 析構時不會自動銷毀所指向的物件 qsharedpointer 引用計數型智慧型指標 可以被自由的拷貝和賦值 當引用計數為0時才刪除指向的物件 include include using namespace std clas...

智慧型指標類模板(中) Qt中的智慧型指標

qt中的智慧型指標 qpointer 當其指向的物件被銷毀時,它會被自動置空 析構時不會自動銷毀所指向的物件 qsharedpointer 引用計數型智慧型指標 可以被自由的拷貝和賦值 當引用計數為0時才刪除指向的物件 include include using namespace std clas...

Qt智慧型指標

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