智能指針是一種資源管理類,經過對原始指針進行封裝,在資源管理對象進行析構時對指針指向的內存進行釋放;一般使用引用計數方式進行管理。html
一個基本實現以下:java
1 class Counter{ 2 public: 3 friend Class SmartPointer; 4 Counter() { 5 ptr = NULL; 6 cnt = 0; 7 } 8 9 Counter(Object* p) { 10 ptr = p; 11 cnt = 1; 12 } 13 14 ~Counter() { 15 delete ptr; 16 } 17 private: 18 Object* ptr; 19 int cnt; 20 }; 21 22 Class SmartPointer { 23 public: 24 SmartPointer(Object* p) { 25 ptr_counter = new Counter(p); 26 } 27 28 SmartPointer(const SmartPointer& sp) { 29 ptr_counter = sp.ptr_counter; 30 ptr_counter->cnt++; 31 } 32 33 ~SmartPointer() { 34 ptr_counter->cnt--; 35 if (ptr_counter->cnt == 0) { 36 delete ptr_counter; 37 } 38 } 39 40 SmartPointer& operator=(const SmartPointer& sp) { //別忘了const 41 ptr_counter->cnt--; 42 if (ptr_counter->cnt == 0) { 43 delete ptr_counter; 44 } 45 ptr_counter = sp.ptr_counter; 46 ptr_counter->cnt++;
return *this; // 賦值運算符重載都要返回*this 47 } 48 private: 49 Counter* ptr_counter; 50 };
Counter裏的指針是Object*,由於是它也是指向這塊內存的。算法
引用計數類Counter至關於對指針和cnt變量的一個包裝。智能指針裏把全部Object*類型的指針都轉換成Counter*類型來處理。函數
follow up:this
1、如何獲取智能指針所包裝的指針和對象?spa
solution1:(naive).net
定義Object* GetPtr(), Object& GetObject(), 直接返回指針和指針的解引用。指針
solution2:(good)code
對指針的 ->(成員訪問)和 *(解引用)進行運算符重載。【運算符重載原理見此文】htm
即,在成員函數定義里加入這兩個:
1 Object* operator->() { 2 return ptr_counter->ptr; 3 } 4 5 Object& operator*() { 6 return *(ptr_counter->ptr); 7 }
注意:成員訪問符號->的重載是有遞歸性質的。
2、引用計數帶來的問題:循環引用
如何解決循環引用?
把循環引用的一方使用弱引用(weak_ptr),便可解除循環引用。 ref ref2
3、auto_ptr, unique_ptr, shared_ptr的比較
http://blog.csdn.net/worldwindjp/article/details/18843087
目前最基本的垃圾收集算法有四種:
1. 標記-清除算法(mark-sweep),
2. 標記-壓縮算法(mark-compact),
3. 複製算法(copying)
4. 引用計數算法(reference counting)
具體原理:(示意圖可參考ref0)
1.標記-清除算法 ref
缺點:形成大量內存碎片
2.標記-壓縮算法
該算法標記階段和Mark-Sweep同樣,可是在完成標記以後,它不是直接清理可回收對象,而是將存活對象都向一端移動,而後清理掉端邊界之外的內存。
3.複製算法
它將可用內存按容量劃分爲大小相等的兩塊,每次只使用其中的一塊。當這一塊的內存用完了,就將還存活着的對象複製到另一塊上面,而後再把已使用的內存空間一次清理掉,這樣一來就不容易出現內存碎片的問題。
缺點:卻對內存空間的使用作出了高昂的代價,由於可以使用的內存縮減到原來的一半。若是存活對象不少,那麼Copying算法的效率將會大大下降。
4.引用計數算法
缺點:循環引用問題
Generational Collection(分代收集)算法
分代收集算法是目前大部分JVM的垃圾收集器採用的算法。它的核心思想是根據對象存活的生命週期將內存劃分爲若干個不一樣的區域。通常狀況下將堆區劃分爲老年代(Tenured Generation)和新生代(Young Generation),老年代的特色是每次垃圾收集時只有少許對象須要被回收,而新生代的特色是每次垃圾回收時都有大量的對象須要被回收,那麼就能夠根據不一樣代的特色採起最適合的收集算法。
目前大部分垃圾收集器對於新生代都採起Copying算法,由於新生代中每次垃圾回收都要回收大部分對象,也就是說須要複製的操做次數較少;
而因爲老年代的特色是每次回收都只回收少許對象,通常使用的是Mark-Compact算法。