在c++中解決記憶體洩漏的有效方法是使用智慧型指標(smart pointer)。智慧型指標和普通指標的用法類似,只是不需要手動釋放記憶體,而是通過智慧型指標自己管理記憶體釋放。
智慧型指標是儲存指向動態分配(堆)物件指標的類,用於生存期控制,能夠確保在離開指標所在作用域時,自動正確的銷毀動態分配的物件,防止記憶體洩漏。它的一種通用
實現技術是使用引用計數,每使用它一次,內部的引用計數加1,每析構一次,內部引用計數減1,減為0時,刪除所指向的堆記憶體。
c++11 提供了3種智慧型指標:std::shared_ptr、std::uniq_ptr、std::weak_ptr,標頭檔案為
一、shared_ptr 共享的智慧型指標:
一:初始化:
通過 建構函式、std::make_shared輔助函式、reset方法來初始化shared_ptr,優先使用make_shared來構造智慧型指標
std::shared_ptrp(new int(1));
std::shared_ptrp2=p;
std::shared_ptrptr;
ptr.reset(new int(1));
對於乙個未初始化的智慧型指標,可以通過reset方法來初始化。
當智慧型指標中有值的時候,呼叫reset會使引用計數減1,
通過過載bool型別操作符來判斷智慧型指標中是否為空
獲取原始指標:當需要獲取原始指標時,可以通過get方法來返回原始指標
std::shared_ptrptr(new int(1));
int *p=ptr.get();
二:刪除共享指標
(1)刪除指標:
(1)指定刪除器:當p的引用計數為0時,自動呼叫刪除器deleteintptr 來釋放物件的記憶體
void deleteintptr(int* p)
std::shared_ptrp(new int,deleteintptr); //當p的引用計數為0了,就銷毀p
(2)lambda表示式也可以
std::shared_ptrp(new int,(int *p));
(2)刪除陣列指標
(1)shared_ptr管理動態陣列時,需要強制指定刪除器,預設的刪除器不支援陣列刪除指標。
std::shared_ptrp(new int[10],(int *p));
(2)void deleteintptr(int* p)
(3)std::shared_ptrp(new int,deleteintptr); //當p的引用計數為0了,就銷毀p
(4)也可以將std::default_delete 作為刪除器。default_delete的內部是通過呼叫delete來實現功能的:推薦
std::shared_ptrp(new int[10],std::default_delete);
注意:(1) 不能將乙個原始指標直接賦值給乙個智慧型指標
std::shared_ptrp=new int(1);//編譯報錯,不允許直接賦值
(2) 不要用乙個原始指標初始化多個shared_ptr,例如下面這些事錯誤的
int *ptr=new int;
shared_ptrp1(ptr);
shared_ptrp2(ptr);//logic error
(3) 不要在函式實參中建立shared_ptr
function (shared_ptr(new int),g());//有缺陷
正確的寫法應該是先建立智慧型指標: shared_ptrp(new int()); f(p,g());
(4) 通過shared_from_this()返回this指標。不要將this指標作為shared_ptr返回出來,因為this指標本質上是乙個裸指標,因此,這樣可能會導致重複析構。
shared_ptrgetself()
正確做法:讓目標類通過派生std::enable_shared_from_this類,然後使用基類的成員函式shared_from_this來返回shared_ptr
class a:public std::enable_shared_from_this
};std::shared_ptrspy(new a);
std::shared_ptrp=spy->getself(); //正確
(5) 要避免迴圈引用。智慧型指標最大的乙個陷阱是迴圈引用,迴圈引用會導致記憶體洩露:
class a
}//解決方式,在類a、類b中生命的shared_ptr指標有乙個為弱引用指標weak_ptr ,即可解決問題
二、unique_ptr 獨佔的智慧型指標
unique_ptr是乙個獨佔型的智慧型指標,它不允許其他智慧型指標共享其內部的指標.
1、初始化
(1)不允許通過賦值將乙個unique_ptr賦值給另外乙個unique_ptr。
unique_ptrmyptr(new t);
unique_ptrmyotherptr=myptr;//錯誤!! 不能複製
(2)unique_ptr不允許複製,可以通過函式返回給其他的unique_ptr,可以通過std::move來轉移到其他的unique_ptr,之後它就不在擁有原來指標的所有權.
unique_ptrmyptr(new t); //ok
unique_ptrmyotherptr=std::move(myptr);//ok
(3)unique_ptr除了獨占性這個特點之外,還可以指向乙個陣列
std::unique_ptrptr(new int[10]);
ptr[9]=9;//設定最後乙個元素為9
2、刪除指標,指定刪除器
(1)std::unique_ptr指定刪除器的時候需要確定刪除器的型別
std::unique_ptr> ptr(new int(1),[&](int* p));
(2)自定義unique_ptr的刪除器
void deleter(connection *connection)
unique_ptrup(new connection("unique_ptr"), deleter);
另一種使用方法:
class cconnnect
};class deleter
};std::unique_ptrup2(new cconnnect, up1.get_deleter());
三、weak_ptr 弱引用的智慧型指標
弱引用指標weak_ptr是用來監視shared_ptr的,不會使引用計數加1,它不管理shared_ptr內部的指標,主要是為了監視shared_ptr的生命週期,
更像是shared_ptr的乙個助手
(1)初始化:
1:通過use_count()方法來獲得當前觀測資源的引用計數.
shared_ptrsp(new int(10));
weak_ptrwp(sp);
coutweak_ptrwp(sp);
if(wp.expired())
f();
}//輸出:42 gw is expired
4:weak_ptr返回this指標
提到不能直接將this指標返回為shared_ptr,需要通過派生std::enable_shared_from_this類,
並通過其他方法shared_form_this來返回智慧型指標,因為std::enable_shared_from_this類中有乙個weak_ptr,這個weak_ptr用來觀測this智慧型指標,
呼叫shared_from_this()方法時,會呼叫內部這個weak_ptr的lock方法,將所觀測的shared_ptr返回.
5:weak_ptr 解決迴圈引用問題
class a
}(3)
(4)(5)
C 11 STL中的容器
一 順序容器 vector 可變大小陣列 deque 雙端佇列 list 雙向鍊錶 forward list 單向鍊錶 array 固定大小陣列 string 與vector相似的容器,但專門用於儲存字元。二 關聯容器 按關鍵字有序儲存元素 底層實現為紅黑樹 map 關聯陣列 儲存關鍵字 值對 se...
C 11智慧型指標
本文介紹c 的四種智慧型指標,其中後三種是c 11新增加的,auto ptr已被棄用。要編譯c 11,需要安裝g 4.8 sudo add apt repository ppa ubuntu toolchain r test sudo apt get update sudo apt get inst...
c 11 智慧型指標
如果在程式中使用new從堆 自由儲存區 分配記憶體,等到不需要時,應使用delete將其釋放。c 引入了智慧型指標auto ptr,以幫助自動完成這個過程。c 11摒棄了auto ptr,並新增了三種智慧型指標 unique ptr,shared ptr,weak ptr。一.auto ptr,un...