您好,登錄后才能下訂單哦!
RALL:資源分配即初始化,定義一個類來封裝資源的分配和釋放,在構造函數中完成資源的分配和初始化,在析構函數中完成資源的清理。
首先來看這樣一個例子:
此例子乍一看上去,new/delete匹配,并沒有什么錯。但就因為return的存在,使得Test()函數提前結束,并沒有執行delete p。這就使得內存泄露。
內存泄露的危害:使得可用內存越來越少,下一次開辟可能不夠,程序崩潰。
為解決此類問題,引入智能指針。
所謂的智能指針就是智能/自動化的管理指針所指向的動態資源的釋放。
智能指針的行為類似于常規指針,重要的區別在于它負責自動釋放所指向的對象。
智能指針也是模板,當我們創建一個智能指針時,需要提供指針可以指向的類型。
智能指針有:auto_ptr,scoped_ptr,shared_ptr,scoped_array,shared_array
1.auto_prt的模擬實現(以前)
注:以前的auto_ptr看起來已經實現的挺好的,多個指針指向同一塊內存,并且釋放的時候也正確。
但是在實現的時候,會出現"野指針"。也就是所謂的"懸掛指針"。
在析構函數中,只是對擁有管理權者進行了析構。在delete內存之后重置指針的方法只對這個指針有效,對其他任何指向(已釋放的)內存的指針是沒有作用的。所以會出現"野指針"。
為解決"野指針"問題,可以將管理權轉交后,將以前的指針賦為NULL。也就是auto_ptr的現代寫法。
auto_ptr的現代寫法:
注:雖然此方法解決了"野指針"的問題,但是在拷貝構造和賦值后,只有一個指針有效。其他的都已為NULL,但有時候會對NULL指針進行引用,使得程序崩潰。
2.簡單粗暴的scoped_ptr
scoped_ptr不允許拷貝構造和賦值,在C++11標準中叫unique_ptr
注:為了防拷貝和賦值
(1)只將拷貝構造和賦值函數聲明不定義
(2)將拷貝構造和賦值函數聲明為private或protected,防止別人搞破壞
3.允許拷貝和賦值的shared_ptr
shared_ptr是通過一個引用計數來記錄該塊空間被共享了幾次,只有當計數器為0時才被釋放。
4. 簡單粗暴的scoped_array
scoped_array和scoped_ptr類似,是為了防拷貝和賦值。但是scoped_array是對數組來說的,因此在析構時要特別注意,應該使用delete[]來釋放內存。
注:scoped_ptr是為了防拷貝和賦值。因此只將拷貝和賦值聲明而不定義,并且將拷貝和賦值聲明為private或者protected,防止他人搞破壞。
5.允許拷貝和賦值的shared_array
shared_array和shared_ptr類似。也是使用了一個引用計數。但是shared_array是對數組來說的。因此在析構時應使用delete[]。
6.現代版的shared_ptr看起來不錯,但是會出現以下幾個問題
(1)循環引用
(2)定置刪除器
6.1循環引用
為了解決循環引用,應該使用弱指針weak_ptr(防止引用計數的增加)
注:所謂的weak_ptr就是用來服務shared_ptr。將一個weak_ptr綁定一個shared_ptr上不會改變shared_ptr的引用計數。
6.2 定置刪除器
我們都只到shared_ptr只能釋放new開辟出來的空間。而對于malloc開辟出來的空間,以及fopen打開的文件不能處理。為了能夠處理各種情況,引入定置刪除器。而定置刪除器的實現是通過operator()即重載()來實現的。
測試結果:
注:任何情況下都不要使用auto_ptr。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。