智能指針主要用於管理在堆上分配的內存,它將普通的指針封裝爲一個棧對象。當棧對象的生存週期結束後,會在析構函數中釋放掉申請的內存,從而防止內存泄漏。ios
智能指針的做用是管理一個指針,由於存在如下這種狀況:申請的空間在函數結束時忘記釋放,形成內存泄漏。使用智能指針能夠很大程度上的避免這個問題,由於智能指針就是一個類,當超出了類的做用域是,類會自動調用析構函數,析構函數會自動釋放資源。因此智能指針的做用原理就是在函數結束時自動釋放內存空間,不須要手動釋放內存空間,有效避免內存泄漏的問題。 c++
智能指針定義於 memory (非memory.h)中, 命名空間爲 std函數
unique_ptr,是用於取代c++98的auto_ptr的產物指針
unique_ptr 獨佔所指向的對象, 同一時刻只能有一個 unique_ptr 指向給定對象(經過禁止拷貝語義, 只有移動語義來實現), 定義於 memory (非memory.h)中, 命名空間爲 std.調試
(C++98的方案,C++11已經拋棄)採用全部權模式。
auto_ptr 適合用來管理生命週期比較短或者不會被遠距離傳遞的動態對象, 最好是侷限於某個函數內部或者是某個類的內部.code
因爲 auto_ptr 基於排他全部權模式:兩個指針不能指向同一個資源,複製或賦值都會改變資源的全部權。對象
#include <iostream> #include <memory> class Test { public: void print() { std::cout << "Test::Print" << std::endl; } }; int main() { std::auto_ptr<Test> pTest1(new Test); pTest1->print(); std::auto_ptr<Test> pTest2(pTest1); //複製構造函數 pTest2->print(); std::cout << "pTest1 pointer:" << pTest1.get() << std::endl; //auto_ptr類的成員函數get()返回一個原始的指針 std::cout << "pTest2 pointer:" << pTest2.get() << std::endl; return 0; } //打印結果: Test::Print Test::Print pTest1 pointer:00000000 pTest2 pointer:01659548 //通過複製構造以後,pTest1所指向資源的全部權轉向了pTest2,而pTest1變成空,兩者不能同時共享該資源。
auto_ptr 主要有兩大問題:生命週期
基於引用計數模型。資源能夠被多個指針共享,它使用計數機制來代表資源被幾個指針共享。內存
每次有 shared_ptr 對象指向資源,引用計數器就加1;當有 shared_ptr 對象析構時,計數器減1;當計數器值爲0時,被指向的資源將會被釋放掉。且該類型的指針可複製和可賦值,即其可用於STL容器中。此外,shared_ptr 指針可與多態類型和不徹底類型一塊兒使用。資源
std::shared_ptr 智能指針共享所指向的資源(全部權),即幾個 shared_ptr 可同時擁有一個對象,且共享一個控制塊(constrol block),包含指向資源的 shared_ptr對象個數、指向資源的 weak_ptr 對象個數以及刪除器(deleter:用戶自定義的用於釋放資源的函數,能夠默認沒有)。
一個空的 shared_ptr 對象不擁有任何資源和控制塊。另外一方面,一個 shared_ptr 初始化爲一個NULL 指針和一個控制塊,這有別有空的 shared_ptr。當共享的引用計數器爲0時,資源釋放(delete 操做符釋放,或由用戶提供的 刪除器 釋放它)。
#include <iostream> #include <memory> class Test { public: void print() { std::cout << "Test::Print" << std::endl; } }; int main() { std::shared_ptr<Test> pTest1(new Test); pTest1->print(); std::shared_ptr<Test> pTest2(pTest1); //複製構造函數 pTest2->print(); std::cout << "pTest1 pointer:" << pTest1.get() << std::endl; //shared_ptr類的成員函數get()返回一個原始的指針 std::cout << "pTest2 pointer:" << pTest2.get() << std::endl; std::cout << "count pTest1:" << pTest1.use_count() << std::endl; //shared_ptr類的成員函數use_count():返回多少個智能指針指向某個對象,主要用於調試。 std::cout << "count pTest2:" << pTest2.use_count() << std::endl; return 0; } //打印結果: Test::Print Test::Print pTest1 pointer:00C29550 pTest2 pointer:00C29550 count pTest1:2 count pTest2:2 //pTest2建立後,pTest1對資源的全部權並無被剝奪,而是pTest1 和 pTest2 均指向了資源,且此時資源的引用計數爲2。當兩個shard\_ptr 指針pTest一、pTest2 超過其做用域時,最後一個析構的指針將會導致資源的釋放(由於引用計數爲0了)。
待補充。。。
shared_ptr相互引用,那麼這兩個指針的引用計數永遠不可能降低爲0,資源永遠不會釋放。
沒法檢測出循環引用,這會形成資源沒法釋放,從而致使內存泄露。
爲了 fix 這個問題,C++11引入了另外一個智能指針:weak_ptr
weak_ptr是用來解決shared_ptr相互引用時的死鎖問題,若是說兩個shared_ptr相互引用,那麼這兩個指針的引用計數永遠不可能降低爲0,資源永遠不會釋放。它是對對象的一種弱引用,不會增長對象的引用計數,和shared_ptr之間能夠相互轉化,shared_ptr能夠直接賦值給它,它能夠經過調用lock函數來得到shared_ptr。
做用在於協助 shared_ptr 工做,可得到資源的觀測權,像旁觀者那樣觀測資源的使用狀況。觀察者意味着 weak_ptr 只對 shared_ptr 進行引用,而不改變其引用計數,當被觀察的 shared_ptr 失效後,相應的 weak_ptr 也相應失效。
weak_ptr更像是shared_ptr的助手:
待補充。。。