智慧型指標總結

2021-10-11 01:47:43 字數 4753 閱讀 5300

unique_ptr

weak_ptr

智慧型指標與常規指標的區別

智慧型指標的選擇

智慧型指標並非c++11的原創,boost庫很早就提供了share_ptr和weak_ptr,c++11在此基礎上增加了unique_ptr,從而形成了我們現在所說的智慧型指標。

智慧型指標主要用於管理動態記憶體,當智慧型指標過期時,這些記憶體將自動釋放;智慧型指標也是模板,當我們建立智慧型指標時,需要提供其所指向的型別;

可以從 auto_ptr 的建構函式來了解一下智慧型指標的基本構成:

template

<

class

x>

class

atuo_ptr

從上面可以看出,智慧型指標中儲存了乙個指標成員,在建構函式中傳入賦值;目前 auto_ptr 已經被棄用,主要原因在於:當 auto_ptr 進行賦值時,將會進行所有權轉讓,但是失去所有權的指標將不再指向有效資料,如果此時還要使用該指標就會出現問題;

shared _ptr 允許多個指標指向同乙個物件;其基本原理是:使用引用計數,賦值時,計數將加 1,指標過期時,計數將減 1,當最後乙個指標過期時,才呼叫指標成員的析構函式進行析構;

指向相同資源的所有 shared _ptr 共享「引用計數管理區域」,並採用原子操作保證該區域中的引用計數被互斥的訪問,該「引用計數管理區域」由其基類指標指向它,當我們進行 shared _ptr 的拷貝時,我們可以認為該基類指標使用的是一種淺拷貝,也就是無論拷貝多少次,「引用計數管理區域」都不會被重新建立,而是引用計數增 use _count _增 1,反之 use _count _減 1;(參考鏈結)

shared_ptr的建構函式將使引用計數加1,析構函式使引用計數減1,這個不必再贅述,但我們需要注意拷貝建構函式與賦值運算子對引用計數帶來的不同,考慮下面**將會帶來什麼效果;

shared_ptrp(

newt()

);shared_ptrq(

newt()

);p = q;

//#3

shared_ptr

p1(p)

;//#4

拷貝建構函式(#4)將會增加 p 所指向物件的引用計數;賦值運算子(#3)可以視作 q 所指向的物件對 p 所指向的物件進行了覆蓋,所以此操作會遞減 p 所指向物件的引用計數,而會遞增 q 的引用計數;

shared_ptr的引用計數本身是安全且無鎖的,乙個shared_ptr可以被多個執行緒安全讀取,但是如果有寫操作則需要加鎖,否則可能會有race condition 發生,建議使用原子操作:std::atomic_…std::shared_ptr;

shared_ptr構造時需要顯式的呼叫new,但是shared_ptr也提供了乙個消除了顯式呼叫new的函式,就是make_shared(),我們可以像下面這樣使用:

shared_ptr sp = make_shared

("make_shared"

);

make_shared()函式最多可以接收10個引數,然後將它們傳遞給型別t,make_shared()的建立比直接使用建構函式要更快,因為它內部只分配一次記憶體,消除了shared_ptr構造時的開銷;

我們當然可以這樣使用shared_ptr和容器:shared_ptr;但是更多的我們是希望智慧型指標作為容器元素,在這一點上,shared_ptr能夠和標準容器完美配合,因為標準容器要求元素可賦值、可複製,如果要排序,還要可比較,而shared_ptr確實符號上述需求。此外還有乙個便利就是:我們不需要寫額外的大量**來保證指標最終被正確刪除,如果使用普通指標存放在容器中這是需要的,但是shared_ptr省略了這一步,並不需要擔心資源洩露。示例如下:

#include

#include

#include

#include

#include

using

namespace std;

intmain

(int argc,

char

*ar**)

cout << endl;

shared_ptr<

int> p = v[9]

;*p =

100;

cout <<

*v[9

]<< endl;

return0;

}

智慧型指標和工廠模式簡直就是絕配,不再返回乙個原始指標,而是乙個被shared_ptr包裝的智慧型指標,可以很好的保護系統資源,更好地控制對介面地呼叫,這也是《efective c++》中強力推薦地使用方式之一。

class

socket_t(.

..);

socket_t*

open_socket()

void

close_socket

(socket_t* s)

socket_t* s =

open_socket()

;shared_ptr

p(s,close_socket)

;//傳入刪除器

在同一時刻只能有乙個 unique_ptr 指向給定物件,當我們進行賦值時會進行所有權讓,所以 unique_ptr 和 auto_ptr 比較類似,但是如果只是如此,那麼將無法避免 auto_ptr 的缺陷,所以 unique_ptr 對此進行了修正:當程式試圖將乙個 unique_ptr 賦給另乙個時,如果源 unique_ptr 是個臨時右值,編譯器允許這樣做,但是如果 unique_ptr 將存在一段時間,編譯器將禁止這麼做;

unique_ptrp3(

newstring

("auto"))

;unique_ptr p4;

p4 = p3;

//#6

編譯器會認為#6 非法,避免了 p3 不再指向有效資料的問題;

unique_ptr

demo

(const

char

* s)

unique_ptr ps;

ps =

demo

("uniquely special"

);

上述操作允許,因為 ps 接管了所有權,而原有 unique_ptr 物件被銷毀了;

weak_ptr 是一種弱引用,指向 shared_ptr 所管理的物件;將乙個 weak_ptr 繫結到乙個 share_ptr 不會改變 shared_ptr 的引用計數,一旦最後乙個指向物件的 share_ptr 被銷毀,物件就會被釋放,即使有 weak_ptr 指向物件,物件還是會被釋放,因此它是一種弱共享;

我們可以像下面這樣使用 weak_ptr:

#include

using

namespace std;

intmain()

if(shared_ptr<

int> p3 = p2.

lock()

)return0;

}

需要注意的是:我們不能使用 weak_ptr 直接訪問物件,因為 weak_ptr 並沒有過載 operator->和 operator *操作符,因此不可直接通過 weak_ptr 使用物件,典型的用法是呼叫其 lock 函式來獲得 shared_ptr 示例,進而訪問原始物件;

同時由於 weak_ptr 所指向的物件有可能不存在,因此上述**使用了 lock,該函式的作用是:如果weak_ptr所指向的shared_ptr物件已經析構,那麼lock返回空,否則返回乙個shared_ptr物件,該物件會導致weak_ptr所指向的shared_ptr引用計數+1;

那麼 weak_ptr 到底有什麼用呢?從上面我們可以看出,使用 weak_ptr 是通過間接呼叫 share_ptr,那麼為什麼不直接使用 share_ptr 就好了呢?

weak_ptr 是為了解決 shared_ptr 存在的環形引用問題;

class

parent

class

child

shared_ptrpa(

new parent)

;shared_ptrpb(

new child)

;pa-

>child = pb;

pb->parent = pa;

上述**將會存在這樣乙個困境:兩個物件各自包含指向彼此的 shared_ptr 成員,形成環狀引用,引用計數永遠為 1,不能銷毀,造成記憶體洩漏;

如果我們將上述**中的類成員的 shared_ptr 使用 weak_ptr 代替,即如下所示:

class

parent

class

child

shared_ptrpa(

new parent)

;shared_ptrpb(

new child)

;pa-

>child = pb;

pb->parent = pa;

那麼根據 weak_ptr 的特性,其不會增加 shared_ptr 的引用計數,從而打破了 shared_ptr 的環狀引用問題;

智慧型指標和常規指標確實很類似,但是還是存在一定區別,例如:

shared_ptr p =

newstring()

;

上述賦值並不能成立,因為 p 是智慧型指標,而非指標,智慧型指標中包含指標成員,只能通過其建構函式來初始化,當沒有初始化時,該指標指向空;

智慧型指標總結

1.智慧型指標的原理 1 智慧型指標不是通常意義下的指標,而是乙個模板類,在對模板類例項化之後會產生類似於指標的行為。通過物件來管理資源。2 智慧型指標採用一種raii 資源分配即初始化 機制,在建構函式中實現對資源的分配及初始化,在析構函式中實現對資源的析構及 2.智慧型指標的分類 c 中最開始是...

智慧型指標總結

std shared ptr include class test public std enable shared from this void print intid int main std enable shared from this是乙個模板類,其中有乙個成員函式 shared ptrs...

智慧型指標總結

分類 通用程式設計技術 2010 02 27 15 46 131人閱讀 收藏 舉報 c 中沒有垃圾 所有的記憶體都要自己管理,也就是說new 與 delete必須由程式設計師自己去一一對應起來。這個難免會出現這樣那樣的記憶體問題。在這種背景下,智慧型指標應運而生。智慧型指標的最終的目的是將一塊記憶體...