發展歷史
C++98中產生了第一個智能指針auto_ptr;
C++boost給出了更實用的scoped_ptr和shared_ptr和weak_ptr;
C++TR1,引入了shared_ptr等,不過TR1并不是標準版;
C++11引入了unique_ptr和shared_ptr和weak_ptr。需要注意的是unique_ptr對應boost的scoped_ptr,并且這些智能指針的實現原理是參考boost中的實現的。
RAII
RAII(Resource Acquisition Is Initialization)是一種利用對象生命周期來控制程序資源(如內存、文件句柄、網絡連接、互斥量等等)的簡單技術。
在對象構造時獲取資源,接著控制對資源的訪問使之在對象的生命周期內始終保持有效,最后在對象析構的時候釋放資源。借此我們實際上把一份資源的責任托管給了一個對象。這種做法有兩大好處:
? ? ? ? 不需要顯式地釋放資源;
? ? ? ? 采用這種方式,對象所需的資源在其生命期內始終保持有效;
各個版本智能指針的特點
auto_ptr
管理權轉移思想,是一個失敗設計
unique_ptr
簡單粗暴,防拷貝,獨占對象的所有權,由于沒有引用計數,性能較好。可以通過std::move來轉移到其他的unique_ptr。
shared_ptr
通過引用計數的方式來實現多個shared_ptr對象之間共享資源:
? ? ? ? shared_ptr在其內部,給每個資源都維護了一份計數,用來記錄該份資源被幾個對象共享;
? ? ? ? 在對象被銷毀時(也就是洗后函數調用),就說明自己不適用該資源了,對象的引用計數減一;
? ? ? ? 如果引用計數時0,就說明自己是最后一個使用該資源的對象,必須釋放該資源;
? ? ? ? 如果不是0,就說明除了自己還有其他對象在使用該份資源,不能釋放該資源,否則其他對象就成野指針了。
????????共享對象的所有權,但性能略差。
如果希望只有一個智能指針管理資源或者管理數組就用unique_ptr,如果希望多個智能指針管理同一個資源就用shared_ptr。
weak_ptr
weak_ptr 是一種不控制對象生命周期的智能指針, 它指向一個 shared_ptr 管理的對象. 進行該對象的內存管理的是那個強引用的shared_ptr, weak_ptr只是提供了對管理對象的一個訪問手段。
weak_ptr 設計的目的是為配合 shared_ptr 而引入的一種智能指針來協助 shared_ptr 工作, 它只可以從一個 shared_ptr 或另一個 weak_ptr 對象構造, 它的構造和析構不會引起引用記數的增加或減少。
什么是循環引用?怎么解決?
share_ptr雖然已經很好用了,但是有一點share_ptr智能指針還是有內存泄露的情況,當兩個對象相互使用一個shared_ptr成員變量指向對方,會造成循環引用,使引用計數失效,從而導致內存泄漏。?
循環引用發生在兩個或多個shared_ptr實例相互引用,形成一個閉環時。因為每個 shared_ptr 在被銷毀之前都會檢查其引用計數,只有當引用計數為零時才會釋放對象,所以循環引用會導致對象無法被釋放,即使沒有其他外部引用指向它。?
weak_ptr配合share_ptr,解決循環引用問題。可以在一個類中使用weak_ptr來引用另一個類的實例,從而打破循環引用。?