auto_ptrc++ |
用於解決資源自動釋放問題,見以下代碼: if (error occur) |
unique_ptr函數 |
unique_ptr做爲auto_ptr替代品。它對引用對象全部權專注,所以得名unique unique_ptr<Obj> ap(new Obj() ); unique_ptr<Obj> two = one; //errorc++11 也就是unique_ptr對對象的引用專注,不容許隨意轉移。對象 2) 可進行移動構造和移動賦值操做 |
shared_ptr內存 |
auto_ptr和unique_ptr只能用一個智能指針引用對象,而shared_ptr則是能夠多個智能指針同時擁有一個對象。shared_ptr實現方式是採用引用計數。引用計數原理即多個智能指針同時引用一個對象,每當引用一次,引用計數加1,當一個智能指針銷燬,引用計數減1,當引用計數減小到0的時釋放引用對象。這種引用計數增減發生在智能指針的構造函數,複製構造函數,賦值操做符,析構函數中。這種方式使得多個智能指針同時對所引用的對象有擁有權,同時在引用計數減到0以後自動釋放資源,也實現了auto_ptr和unique_ptr的資源釋放功能。 } |
weak_ptr |
shared_ptr是一種強引用的關係,智能指針直接引用對象。那麼這個代碼有一個隱含的問題,就是循環引用,從而形成內存泄漏。示例看一個循環引用的例子。 |
應用總結 |
儘可能使用unique_ptr而不是auto_ptr shared_ptr知足大部分需求; weak_ptr避免遞歸的依賴關係; |
make_shared | 1. 在初始化unique_ptr或者shared_ptr時,優先使用std::make_unique和std::make_shared。緣由: 1)異常安全性 假設有以下函數聲明: intcomputePriority(); processInvestment(std::shared_ptr<Investment>(newInvestment()),computePriority()); 因爲在C++中函數參數的執行順序不固定,因此在上面對函數processInvestment調用中,函數參數的執行順序極可能是: new Investment computePriority() std::shared_ptr constructor 這種執行順序的風險是,若是在第二步,執行computePriority的過程當中出現異常,那麼在第一步中new出來的對象將變得不可訪問,從而形成內存泄漏。 2)執行效率(對於shared_ptr而言) std::shared_ptr<Investment>ptr(new Investment); //方式1,new的方式在方式1中,會涉及到兩次動態內存分配: 第1次是new Investment時,爲Investment對象分配空間; 第2次是爲控制塊(Control Block)分配空間。 auto pIn = std::make_shared<Investment>();//方式2,make_shared的方式 在方式二中,一次動態內存分配就足夠了,這是因爲make_shared會爲Investment對象和控制塊(Control block)一次性分配一大塊內存。因爲只有一次內存分配,於是方式二提升了程序的執行效率。 二、make_xxx函數的弊端 既然使用make_xxx有這麼多好處,是否應到處使用make函數而徹底放棄new方式?固然不是,make函數存在如下限制: 1) make函數不支持用戶自定義釋放器。因爲make函數有本身的內存分配和析構規則,因此不適用於自定義分配器和釋放器的對象。 2) make函數不支持大括號初始化方式。對於下面這句代碼: auto spv = std::make_shared<vector<int>>(10,20); 意爲spv指向一個vector,該vector有10個元素,每一個元素值爲20。若是想實現的是這個vector有兩個元素,分別爲10,20的話,只能用new方式。 3) 內存釋放不夠靈活。 在使用new的方式中,有兩塊獨立的堆內存,一塊存放資源對象,一塊存放控制塊,當資源對象的引用計數爲0的時候,資源對象會被銷燬,它所佔用的內存也會被隨之銷燬。 在使用make函數的方式中,make函數一次性爲資源對象和控制塊分配了一塊內存,當資源對象的引用計數爲0是,對象被銷燬,可是資源對象佔用的內存卻不會被銷燬,只有當控制塊佔用的內存被銷燬是纔會將資源對象所佔內存一併釋放。那麼,控制塊內存何時被釋放呢?這就涉及到控制塊中另外一個引用計數了,這個引用計數被稱爲「Weak Count」,其做用是用來計數指向該資源的weak_ptr的數量。當這個weak count的值爲0時,控制塊纔會被釋放。當資源對象很是龐大時,使用make函數的方式將形成不小的資源浪費。 |