智慧型指標
參考:我們知道除了靜態記憶體和棧記憶體外,每個程式還有乙個記憶體池,這部分記憶體被稱為自由空間或者堆。程式用堆來儲存動態分配的物件即那些在程式執行時分配的物件,當動態物件不再使用時,我們的**必須顯式的銷毀它們。
在c++中,動態記憶體的管理是用一對運算子完成的:new和delete,new:在動態記憶體中為物件分配一塊空間並返回乙個指向該物件的指標,delete:指向乙個動態獨享的指標,銷毀物件,並釋放與之關聯的記憶體。
動態記憶體管理經常會出現兩種問題:一種是忘記釋放記憶體,會造成記憶體洩漏;一種是尚有指標引用記憶體的情況下就釋放了它,就會產生引用非法記憶體的指標。
為了更加容易(更加安全)的使用動態記憶體,引入了智慧型指標的概念。智慧型指標的行為類似常規指標,重要的區別是它負責自動釋放所指向的物件。標準庫提供的兩種智慧型指標的區別在於管理底層指標的方法不同,
shared_ptr允許多個指標指向同乙個物件,unique_ptr則「獨佔」所指向的物件。標準庫還定義了一種名為weak_ptr的伴隨類,它是一種弱引用,指向shared_ptr所管理的物件,這三種智慧型指標都定義在memory標頭檔案中。
常用智慧型指標:shared_ptr,unique_ptr和weak_ptr
shared_ptr允許多個指標指向同乙個物件,unique_ptr則「獨佔」所指向的物件。標準庫還定義了一種名為weak_ptr的伴隨類,它是一種弱引用,指向shared_ptr所管理的物件,這三種智慧型指標都定義在memory標頭檔案中。
shared_ptr p3 = make_shared(42);shared_ptr
p4 = make_shared(10,'9'
);shared_ptr
p5 = make_shared();
//可以通過呼叫release或reset將指標所有權從乙個(非const)unique_ptr轉移給另乙個unique
//將所有權從p1(指向string stegosaurus)轉移給p2
unique_ptr p2(p1.release());//
release將p1置為空
unique_ptr p3(new
string("
trex
"));
//將所有權從p3轉移到p2
p2.reset(p3.release());//
reset釋放了p2原來指向的記憶體
shared_ptr和unique_ptr用法:
shared_ptrsp; //空指標,可以執行型別為t 的物件
unique_ptrup;
p
//p看做乙個條件判斷,若p指向乙個物件,則為true
*p //
獲取它指向的物件
p->mem //
等價於(*p).mem
p.get() //
返回p中儲存的指標。
swap(p,q) //
交換p和q中的指標
p.swap(q)
share_ptr:
make_share(args) //返回乙個shared_ptr,指向乙個動態分配的型別為t的物件,使用args初始化。
share_ptrp(q) //
p是shared_ptr q的拷貝,此時會增加q中計數器,q中的指標必須轉換為t*;
p = q //
p和q都是shared_ptr,所儲存的指標必須能相互轉換。此操作會遞減p的引用計數,
//遞增q的引用計數。若p的引用計數為0,則將其管理的記憶體釋放。
p.unique() //
若p.use_count()為1,則返回 true;否則返回 false
p.use_count() //
返回與p共享物件的智慧型指標數量;可能很慢,主要用於除錯。
unique_ptr:
//由於乙個unique_ptr擁有它指向的物件,因此unique_ptr不支援普通的拷貝或賦值操作。
unique_ptru1 //空unique_ptr,可以指向型別為t的物件。u1會使用delete來釋放它的指標;
unique_ptru2 //
u2會使用乙個型別為d的可呼叫物件來釋放它的指標。
unique_ptru(d) //
空unique_ptr,指向型別為t的物件,用型別為d的物件d代替delete
u=nullptr //
釋放u指向的物件,將u置為空
u.release() //
u放棄對指標的控制,將u置為空
u.reset()
//釋放u指向的物件
u.reset(q) //
如果提供了指標q,將u指向這個物件,否則將u置為空。
u.reset(nullptr)
weak_ptr:
weak_ptr是一種不控制所指向物件生存期的智慧型指標,它指向乙個由shared_ptr管理的物件,將乙個weak_ptr繫結到乙個shared_ptr不會改變shared_ptr的引用計數。一旦最後乙個指向物件的shared_ptr被銷毀,物件就會被釋放,即使有weak_ptr指向物件,物件還是會被釋放。
weak_ptrw //空weak_ptr 可以指向為t的物件
weak_ptrw(sp) //
與shared_ptr sp 指向相同物件 weak_ptr
w = p //
p可以是share_ptr 或weak_ptr
w.reset() //
w 為空
w.use_count //
與w共享物件的shared_ptr豎向
w.expired() //
w.use_count() 為0 ,返回true,否則返回為false
w.lock() //
如果expired 為true,則返回乙個空shared_ptr,否則返回乙個指向w物件的shared_ptr
weak_ptr 舉例
#include #include#include
using
namespace
std;
class
test
~test()
void func()
private:
intdata;
};class
teacher
~teacher()
shared_ptr
stu;
};class
student
~student()
//如果換成shared_ptrtea;就會形成迴圈引用,導致記憶體洩漏
weak_ptrtea;
};int
main()
std::move
型別轉換static_cast::type &&>(t);
std::move語句可以將左值變為右值而避免拷貝構造。將物件的狀態或者所有權從乙個物件轉移到另乙個物件。
左值:放在等號左邊的值,可以被賦值: a; ++a; *a;**a;a.m;a->m;a[m]
右值:放在等號右邊的值,不能被賦值;a+b; a++; a&&b; a深拷貝:a先申請出一片新的空間,完全複製b的內容到新空間中;
淺拷貝:a複製b指標,將自己的指標指向b的內容位址,a、b公用一塊記憶體位址;
a = std::move(b); a 對 b 實現淺層拷貝,為了防止b的改變影響到a ,對b清除。
參考:舉例:
#include #include#include
#include
intmain()
智慧型指標 強弱智慧型指標
在平時編寫 的時候經常會用到new來開闢空間,而我們開闢出來的空間必須得手動去delete他,但是如果程式設計師忘記去手動釋放那邊會出現乙個麻煩的問題,記憶體洩漏!或者是一塊記憶體被多個函式同時使用時,如果其中乙個函式不知道還有其他人也在使用這塊記憶體而釋放掉的話同樣也會引起程式的崩潰。引起記憶體洩...
智慧型指標學習
最近接觸到智慧型指標很多,於是研究了一下智慧型指標的原理,寫下自己的心得體會,有不對的還請指正。智慧型指標產生的目的 因為在c 中,存在非常複雜的指標錯誤問題,例如,某個物件生成後,指向該物件的指標可能有多個,當我們用delete語句刪除其中的乙個指標後,物件就被銷毀,那麼其餘指向該物件的指標就會懸...
智慧型指標3
include include using namespace std define test smartptr class stub class sentry sentry private int lock template class refcountingtraits void unrefer...