今天讓我們來分析一下c++中的智慧型指標和異常,首先呢先普及一下概念!
(1)智慧型指標:智慧型或者自動化的管理指標所會向的動態資源的釋放。
(2)異常:當乙個函式發現自己無法處理的錯誤時,讓函式的呼叫者直接或間接的處理這個問題。
(3)raii:資源分配即初始化。建構函式完成物件的初始化,析構函式完成物件的清理,而不是刪除。
在實際寫**過程中,我們很容易寫出存在異常的**,不信來看看下面幾個例子 :
void test()
delete p;
}
很容易可以看出在if語句中已經返回了,那後面的**自然是執行不了了,所以就出現了記憶體洩露的危險,這可是非常可怕的呢 ,它可能會耗盡記憶體,不僅當前程式會崩潰,嚴重的整個系統都會崩潰,這是看你怎麼辦,哈哈。這時肯定會有人想到了c++裡面不是有異常捕獲嗎?是的,為了增加**的相容性,c++採用了下面的**來捕獲異常:
throw 丟擲異常;
trycatch (異常型別)
上面的**進行這樣處理不就沒事了嗎?
void test()
} catch (int e)
delete p;
}
但是這裡在catch中卻二次丟擲異常,這樣管理起來非常混亂。所以就引入了智慧型指標,用它來解決異常更方便。上面提到的raii就是編寫異常安全**的關鍵思想。
下來介紹一下boost庫里的智慧型指標吧。
下面給出這些智慧型指標的模擬實現介面,具體的實現自己完成嘍
(1)autoptr有兩種實現方法
//現**法
template class autoptr
;//舊方法
templateclass autoptr
;
很容易可以看出舊寫法裡多了乙個布林型別的成員變數,大家都知道autoptr採用的是管理權轉移的方式來管理的。所以誰是資源的管理者,誰的_owner值就為true,其他的物件的_owner自然就是false。在現**法中去除了這種方式,直接採用物件賦空的方式,看起來還是舊的寫法似乎更為合理一點,但是新事物的出現肯定有它存在的理由,下來我們看個例子:
autoptrap1(new int(1));
if (某個條件)
大家想到了嗎?對於舊寫法,如果進入if語句,建立ap2後進行拷貝ap1._owner=false,ap2._owner=true;但是出了if**塊,就出了ap2的作用域,ap2被釋放,但ap1裡還儲存著原來的位址,所以可能發生二次釋放或訪問問題,但這個時候ap1就是野指標啦,後果很嚴重呢!
但對於現**法,拷貝後將ap1賦空,想要再用ap1時進行檢測為空,那也就避免使用它啦。
(2)scopedptr
templateclass scopedptr
;
容易看出它裡面直接把拷貝建構函式和過載賦值函式宣告為了保護或者私有的,在類外是不能被呼叫的,也就起到了防拷貝的作用。
(3)sharedptr
templateclass sharedptr
;
(4)scopedarray/sharedarray
templateclass scopedarray;//
templateclass sharedarray
;
這些當中sharedptr是使用最廣泛的,但在上面sharedptr的實現方法中還存在幾個重要的問題:
1,引用計數器更新存在著執行緒安全
對於這個問題呢,我還沒有能力去解決,待我學成歸來,一定收拾它。
2,迴圈引用
我們用乙個簡單的例子來說明一下什麼是迴圈引用
#includestruct node//定義乙個雙向鍊錶
};void testsharedptr()
執行這段**你會發現,咦,為什麼沒有輸出呢?也就是說cur和next根本沒用被釋放。大家看下面的圖
在用sharedptr實現雙向鍊錶時,會發生迴圈引用,這是乙個很特殊的場景。
因為cur->_next和next->_prev相互依賴,所以在出了作用域以後都等著對方釋放,處於一種僵持狀態。因而沒用呼叫析構函式。
解決方法是採用weak_ptr弱指標,如下:
#includestruct node//定義乙個雙向鍊錶
};
weak_ptr在建立物件時引用計數為1,而在cur->_next=next和next->_prev=cur中對cur和next的引用計數不加1,這就很好的解決了迴圈引用的問題。
3,定置刪除器
先介紹乙個概念仿函式,顧名思義它類似於函式但並不是函式,而是乙個類。只不過在類的物件呼叫成員函式的時候特別像是函式的呼叫,也就是在 這個類中過載了operator()。看兩個小例子:
(1)
void testsharedptr()
程式看上去沒有問題,可能也沒有崩潰,可是malloc和free要成對使用,這裡存在記憶體洩露的問題。
(2)
void testsharedptr()
當shared_ptr物件是檔案時,出作用域釋放,系統自然會崩潰。
怎麼解決上面的問題的?
struct free
};struct fclose
};void testsharedptr()
這就是乙個仿函式的使用例項。
那接下來就用它來模擬實現shared_ptr的定置刪除器吧,同樣還是給出介面。
templatestruct defaultdel
};templatestruct free
};template>
class sharedptr
;void testdeleter()
好了,智慧型指標就說這麼多啦。小夥伴明白了嗎?
本文出自 「stand out or get out」 部落格,請務必保留此出處
智慧型指標和異常
使用異常處理的程式能在異常發生後令程式流程繼續,同時要注意的是,這種程式需要確保在異常發生後資源能被正確地釋放。乙個簡單的確保資源被釋放的方法是使用智慧型指標。如果使用智慧型指標,即使程式塊過早結束,智慧型指標類也能確保在記憶體不再需要時將其釋放 void func 在函式結束時shared ptr...
C 異常 與智慧型指標
void func1 上面是個很露骨的 異常不安全 的例子。一旦發生異常,p申請的記憶體將得不到釋放。乙個簡單的辦法是 int p new int 1024 trycatch delete p 還有種方法是定義乙個簡單的類ptr,它含有乙個指標成員。該類的析構函式會釋放這個指標所指物件的記憶體。vo...
智慧型指標和萬能指標
智慧型指標 智慧型指標 smart pointer 是儲存指向動態分配 堆 物件指標的類。除了能夠在適當的時間自動刪除指向的物件外,他們的工作機制很像c 的內建指標。智慧型指標在面對異常的時候格外有用,因為他們能夠確保正確的銷毀動態分配的物件。他們也可以用於跟蹤被多使用者共享的動態分配物件。智慧型指...