第十六章 string類和標(biāo)準(zhǔn)模板庫(2)智能指針模板類

(二)智能指針模板類

智能指針是行為類似指針的類對象,但這種對象還有其他便于管理內(nèi)存的功能。

1.使用智能指針

(1)三個智能指針模板auto_ptr,shared_ptr,unique_ptr,都定義了類似指針的對象,可以將new獲得的地址賦值給這些對象。當(dāng)智能指針過期的時候,其析構(gòu)函數(shù)將使用delete來釋放指針指向的內(nèi)存,也就是向正常的變量那樣使用智能指針,而不用考慮釋放它指向的內(nèi)存

(2)創(chuàng)建智能指針對象,必須包含頭文件memory,然后使用通常的模板實(shí)例化語法來實(shí)例化所需類型的指針。比如auto_ptr<double> pd(new double);就創(chuàng)建了一個智能指針對象pd指向一個double類型的內(nèi)存塊。new double是new返回的指針,它是構(gòu)造函數(shù)auto_ptr<double>的參數(shù)。智能指針也是處于名稱空間std之內(nèi)的,因此需要使用std::運(yùn)算符或前面講過的其他技術(shù)。

(3)所有的智能指針都只有一個explicit構(gòu)造函數(shù),以指針作為參數(shù),當(dāng)然也可以為空指針。智能指針和普通指針的用法幾乎一樣,比如使用*,->等運(yùn)算符。可以將普通指針作為參數(shù)構(gòu)造智能指針,也可以用new分配內(nèi)存返回地址來利用構(gòu)造函數(shù)構(gòu)造智能指針,總之智能指針只可以顯式使用構(gòu)造函數(shù)來構(gòu)造,不允許隱式的賦值和構(gòu)造。

智能指針可以賦值給同類型的常規(guī)指針,智能指針還可以賦值給同類型的智能指針(這樣會產(chǎn)生重復(fù)釋放內(nèi)存的問題,會在后面解決)。

(4)有一點(diǎn)要注意的是,普通指針可以指向非堆上的內(nèi)存,也就是普通的變量,而智能指針只能用于new運(yùn)算符分配的內(nèi)存,否則智能指針刪除的時候要釋放指向內(nèi)存,這在普通變量中是不正確的。

2.有關(guān)智能指針的注意事項(xiàng)

(1)如果兩個智能指針指向同一個對象,智能指針刪除的時候,會釋放同一個對象兩次,這會造成問題,解決的方法有很多種。一種是建立所有權(quán),這是auto_ptr和unique_ptr的策略,但unique_ptr的策略更為嚴(yán)格,這也是auto_ptr被拋棄的原因。第二種是創(chuàng)建智能性更高的指針,只有最后一個指針被釋放時才delete其指向的內(nèi)存,這是shared_ptr的策略。第三種是重新定義賦值運(yùn)算符,進(jìn)行深度復(fù)制,這樣兩個指針指向不同的對象。

(2)atuo_ptr智能指針是用所有權(quán)的形式來解決指針指向同一個內(nèi)存地址的問題的,此時如果一個指針賦值給另一個指針,那么就喪失了所有權(quán)(也就是賦值的智能指針變?yōu)榱丝罩羔?,將指向的對象的所有?quán)交給了被賦值的指針),我如果再用這個指針訪問對象,就會出現(xiàn)問題,這是auto_ptr不利的地方。

(3)unique_ptr為何優(yōu)于auto_ptr?

當(dāng)我們將一個unique_ptr賦值給另一個unique_ptr的時候,如果后者是一個臨時右值,編譯器允許這樣做(比如語句pu3=unique_ptr<string>(new string “yo”);是允許的,因?yàn)樵摌?gòu)造函數(shù)創(chuàng)建的臨時對象,也就是指針,在將值傳遞給pu3之后,將會被銷毀,也就是一個pu3對應(yīng)于一個內(nèi)存地址,這是沒有問題的);而如果源unique_ptr將要存在一段時間,那么編譯器將不允許這樣做,這是在編譯的時候就確定的,如果錯誤會通不過編譯,而auto_ptr不能在編譯期間發(fā)現(xiàn)錯誤。

auto_ptr沒有上面所說的編譯期間糾錯的功能,它可以將一個auto_ptr賦值給另一個auto_ptr,這可能會在很多時候出錯,因此auto_ptr被拋棄不用。

另外,unique_ptr還有一個功能是可以使用new name[]來創(chuàng)建指向數(shù)組的指針,而auto_ptr只能使用new name。比如unique_ptr<double[]> aa(new double[4]);這是可以的,而如果是auto_ptr則是不被允許的,這是因?yàn)閡nique_ptr析構(gòu)函數(shù)定義了delete[]版本而auto_ptr沒有定義。因此,智能指針我們選擇兩種就可以了,一個unique_ptr,另一個shared_ptr,不用考慮其他了。

如果我需要將unique_ptr指針對象賦值給另一個指針對象的時候應(yīng)該怎么辦呢?(意思是我可以確保不會出現(xiàn)內(nèi)存釋放兩次的錯誤,而且希望再用回auto_ptr的功能),此時可以使用std::move函數(shù)將一個unique_ptr對象的內(nèi)容讓渡到另一個對象,比如unique_ptr<string> aa(new string(“what”));unique_ptr<string> bb;bb=aa;(不允許)bb=move(aa);(這是可以的)。

4.選擇智能指針

如果程序需要使用指向同一個對象的多個指針,此時要使用shared_ptr。而如果程序不需要多個指向同一個對象的指針,則可以使用unique_ptr,只有一個指針對對象有所有權(quán),將其賦值給其他unique_ptr指針將不能通過編譯器。

當(dāng)一個unique_ptr屬于右值時,可以將它賦值給一個shared_ptr,這與將一個unique_ptr賦值給另一個unique_ptr滿足的條件是相同的(也就是臨時的unique_ptr是可以賦值給另一個unique_ptr的,此時也可以賦值給一個shared_ptr)。將一個右值(也就是臨時指針)unique_ptr賦值給一個shared_ptr時,unique_ptr會自動轉(zhuǎn)換為shared_ptr,并將內(nèi)存控制權(quán)交給shared_ptr。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 參考資料:《C++ Primer中文版 第五版》我們知道除了靜態(tài)內(nèi)存和棧內(nèi)存外,每個程序還有一個內(nèi)存池,這部分內(nèi)存...
    陳星空閱讀 1,118評論 0 0
  • 1. 什么是智能指針? 智能指針是行為類似于指針的類對象,但這種對象還有其他功能。 2. 為什么設(shè)計(jì)智能指針? 引...
    MinoyJet閱讀 696評論 0 1
  • 導(dǎo)語: C++指針的內(nèi)存管理相信是大部分C++入門程序員的夢魘,受到Boost的啟發(fā),C++11標(biāo)準(zhǔn)推出了智能指針...
    7ee72f98ad17閱讀 1,028評論 0 1
  • 導(dǎo)讀## 最近在補(bǔ)看《C++ Primer Plus》第六版,這的確是本好書,其中關(guān)于智能指針的章節(jié)解析的非常清晰...
    小敏紙閱讀 2,066評論 1 12
  • 由于云南氣候四季如春,旅游勝地不勝枚舉。 我們跟團(tuán)第一站來到了大理古城,8月10日早上乘車去大理古城,導(dǎo)游是一...
    荷韻幽香閱讀 625評論 2 4

友情鏈接更多精彩內(nèi)容