在c++中解決記憶體洩漏的有效方法是使用智慧型指標(smart pointer)。智慧型指標和普通指標的用法類似,只是不需要手動釋放記憶體,而是通過智慧型指標自己管理記憶體釋放。
智慧型指標是儲存指向動態分配(堆)物件指標的類,用於生存期控制,能夠確保在離開指標所在作用域時,自動正確的銷毀動態分配的物件,防止記憶體洩漏。它的一種通用
實現技術是使用引用計數,每使用它一次,內部的引用計數加1,每析構一次,內部引用計數減1,減為0時,刪除所指向的堆記憶體。
c++11 提供了3種智慧型指標:std::shared_ptr、std::uniq_ptr、std::weak_ptr,標頭檔案為
一、shared_ptr 共享的智慧型指標:二、unique_ptr 獨佔的智慧型指標1:初始化:
通過 建構函式、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();
二:刪除shared_ptr共享指標
(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
(5) 要避免迴圈引用。智慧型指標最大的乙個陷阱是迴圈引用,迴圈引用會導致記憶體洩露:class a:public std::enable_shared_from_this
};std::shared_ptrspy(new a);
std::shared_ptrp=spy->getself(); //正確
解決方式:在類a、類b中生命的shared_ptr指標有乙個為弱引用指標weak_ptr ,即可解決問題class a
}
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);
cout<
2:通過expired()方法來判斷所觀測的資源是否已被釋放.
shared_ptrsp(new int(10));
weak_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
}
智慧型指標auto ptr 記憶體洩漏解決
在c 11中,已經不使用auto ptr,而用 unique ptr進行替代,不過二者原理都差不多。標頭檔案 memory 智慧型指標 實質上是乙個類,在建立智慧型指標的時候,本質上是在棧上建立了乙個物件,而析構函式總是會在出棧時被呼叫,清理會自動進行。unique ptr auto ptr 通過在...
c 智慧型指標與記憶體管理
c 中當我們需要新分配記憶體的時候需要手動的去呼叫new顯式的分配一塊記憶體,如果我們在任何中new 如函式中申請空間返回 忘記釋放,或者在 函式執行過程中出現異常,沒 有執行釋放語句 了空間,在不需要使用後忘記了呼叫delete這塊位址的話就會造成 記憶體洩露。為了解決這乙個問題引入了智慧型指標。...
c 用智慧型指標幫我們避免記憶體洩漏問題
c 沒有gc機制,處理堆記憶體時就得小心,所以有了智慧型指標這個玩意。智慧型指標可以理解為普通指標的再封裝,智慧型指標的析構函式包含了對於堆記憶體的釋放操作。unique ptr 同一之間只能有乙個智慧型指標指向該物件 shared ptr 可以有多個shared ptr指向某物件 當引用數量為0時...