C 四種智慧型指標詳解

2021-10-18 23:13:09 字數 3709 閱讀 4142

c++裡面的四個智慧型指標:shared_ptr,unique_ptr,weak_ptr,auto_ptr其中前三個是c++11支援,並且最後乙個已經被11棄用。

智慧型指標的使用

智慧型指標主要用於管理在堆上分配的記憶體,它將普通的指標封裝為乙個棧物件。當棧物件的生存週期結束後,會在析構函式中釋放掉申請的記憶體,從而防止記憶體洩漏。c++11中最常用的智慧型指標型別為 shared_ptr它採用引用計數的方法,記錄當前記憶體資源被多少個智慧型指標引用。該引用計數的內存在堆上分配。當新增乙個時引用計數加1,當過期時引用計數有引用計數為0時,智慧型指標才會自動釋放引用的記憶體資源。對 shared_ptr進行初始化時不能將—個普通指標直接賦值給智慧型指標,因為乙個是指標,乙個是類。可以通過 make_shared函式或者通過建構函式傳入普通指標,並可以通過get函式獲得普通指標。

1. auto_ptr(c++98方案,c++11已棄用)

採用所有權模式

auto_prtp1(

newstring

("hello world"))

;auto_ptr p2;

p2 = p1;

// auto_ptr不會報錯

此時不會報錯,p2剝奪了p1的所有權,但是當程式執行時訪問p1將會報錯。所以auto_pt的缺點是:存在潛在的記憶體崩潰問題!

2. unique_ptr(替換auto_ptr)

unique_ptr實現獨佔式擁有或嚴格擁有概念,保證同時間內只有乙個智慧型指標可以指向該物件。它對於避免資源洩露(例如"以new建立物件後因為發生異常而忘記呼叫 delete")特別有用採用。

採用所有權模式,還是上面那個例子

unique_prtp3(

newstring

("hello world"))

;unique_ptr p4;

p4 = p3;

// 此時程式會報錯

編譯器認為p4=p3非法,避免了p3不再指向有效資料的問題。因此unique_ptr比auto_ptr更安全。

另外 unique_pt還有更聰明的地方:當程式試圖將—個 unique_prt賦值給另—個時,如果源unique_ptr是個臨時右值,編譯器允許這麼做;如果源 unique_ptr將存在一段時間,編譯器將禁止這麼做,比如:

unique_prt

pt1(

newstring

("hello world"))

;unique_ptr pt2;

pt2 = pt1;

// #1 not allowed

unique_ptr pt3;

pt3 = unique_ptr

(new

string

("hello world"))

;// #2 allowed;

其中#1留下懸掛的 unique_ptr(pt1,這可能導致危害。而#2不會留下懸掛的 unique_ptr,因為它呼叫 unique_ptr的建構函式,該建構函式建立的臨時物件在其所有權讓給pt3後就會被銷毀。這種隨情況而已的行為表明,unique_ptr優於允許兩種賦值的 auto_ptr。

注:如果確實想執行類似與#1的操作,要安全的重用這種指標,可給它賦新值。c++有乙個標準庫函式std::move(),讓你能夠將乙個unique_ptr賦給另乙個。例如:

unique_ptr ps1, ps2;

ps1 =

demo

("hello");

ps2 =

move

(ps1)

;ps1 =

demo

("world");

cout <<

*ps2 <<

*ps1 <

3. share_ptrshared_ptr實現共享式擁有概念。多個智慧型針可以指向相同物件,該物件和其相關資源會在「最後—個引用被銷毀」時候釋放。從名字 share就可以看出了資源可以被多個指標共享,它使用計數機制來表明資源被幾個指標共享。可以通過成員函式 use_count()來檢視資源的所有者個數。除了可以通過new來構造,還可以通過傳入 auto_ptr, unique_ptr, weak_ptr來構造。當我們呼叫 release()時,當前指標會釋放資源所有權,計數減一。當計數等於0時,資源會被釋放。

shared_ptr是為了解決 auto_ ptr在物件所有權上的侷限性( auto_ ptr是獨佔的),在使用引用計數的機制上提供了可以共享所有權的智慧型指標。

成員函式:

use_count:返回引用計數的個數

unique:返回是否是獨佔所有權( use_count為1)

swap:交換兩個shared_ptr物件即交換所擁有的物件

reset:放棄內部物件的所有權或擁有物件的變更會引起原有物件的引用計數的減少

get:返回內部物件指標,由於已經過載了()方法因此和直接使用物件是一樣的。如share_ptr sp(new int(1)); sp.get()是等價的

4. weak_ptr

weak_ptr是一種不控制物件生命週期的智慧型指標,它指向乙個shared_ptr管理的物件進行該物件的記憶體管理的是那個強引用的shared_ptr。weak_ptr只是提供了對管理物件的乙個訪問手段。 weak_ptr設計的目的是為配合shared_ptr而引入的種智慧型指標來協助shared_ptr工作,它只可以從乙個 shared_ptr或另乙個weak_ptr物件構造它的構造和析構不會引起引用記數的增加或減少。weak_ptr,是用來解決 shared_ ptr相互引用時的死鎖問題,如果說兩個 shared_ptr相互引用那麼這兩個指標的引用計數永遠不可能下降為0,資源永遠不會釋放。它是對物件的種弱引用,不會增加物件的引用計數,和shared_ptr之間可以相互轉化,shared_ptr可以直接賦值給它,它可以通過呼叫lock函式來獲得shared_ptr。

classb;

classa}

;classb}

;void

fun(

)int

main()

執行結果如下:

可以看到fun函式中pa,pb之間互相引用,兩個資源的引用計數為2,當要跳出函式時,智慧型指標pa,pb析構時兩個資源引用計數會減一,但是兩者引用計數還是為1,導致跳出函式時資源沒有被釋放(a、b的析構函式沒有被呼叫),如果把其中乙個改為 weak_ptr就可以了,我們把類a裡面的 shared_ptr pb:改為 weak_ptr pb。

執行結果如下,這樣的話,資源b的引用開始就只有1,當pb析構時,b的計數變為0,b得到釋放,b釋放的同時也會使a的計數減一,同時pa析構時使a的計數減一,那麼a的計數為0,a得到釋放。

注意的是我們不能通過 weak_ptr直接訪問物件的方法,比如b物件中有乙個方法 print()我們不能這樣訪問,pa->pb-> print();因為pb是個 weak_ptr,應該先把它轉化為shared_ptr,如:shared_ptr p= pa->pb_.locke; p->print();

四種智慧型指標剖析

個人部落格傳送門 智慧型指標是c 中乙個程式設計技巧。它保證記憶體的正確釋放,解決了記憶體洩漏的問題。有乙個思想叫做raii,raii指的是資源分配即初始化。我們通常會定義乙個類來封裝資源的分配和釋放,在建構函式中完成資源的分配和初始化,在析構函式中完成資源的清理。在c 中,我們一般是使用new和d...

stl的四種智慧型指標

第一種 std auto ptr auto ptr是所有權轉移的智慧型指標,也就是同一時刻只有乙個智慧型指標物件對原物件擁有所有權。第二種 std scoped ptr scoped ptr智慧型指標無法使用乙個物件建立另乙個物件,也無法採用賦值的形式。這無疑提公升了智慧型指標的安全性,但是又存在無...

C 裡面四種智慧型指標的使用及區別

介紹 c 裡面有四個智慧型指標 auto ptr,shared ptr,weak ptr,unique ptr 其中後三個是c 11支援,並且第乙個已經被11棄用。智慧型指標的作用?智慧型指標的作用是用來管理乙個指標。為麼要使用智慧型指標?當申請的空間在函式結束時忘記釋放,將會造成記憶體洩漏。而智慧...