很多人談到c++,說它特別難,可能有一部分就是因?yàn)閏++的內(nèi)存管理吧,不像java那樣有虛擬機(jī)動(dòng)態(tài)的管理內(nèi)存,在程序運(yùn)行過程中可能就會(huì)出現(xiàn)內(nèi)存泄漏,然而這種問題其實(shí)都可以通過c++11引入的智能指針來(lái)解決,相反我還認(rèn)為這種內(nèi)存管理還是c++語(yǔ)言的優(yōu)勢(shì),因?yàn)楸M在掌握。 c++11引入了三種智能指針:
shared_ptrshared_ptr使用了引用計(jì)數(shù),每一個(gè)shared_ptr的拷貝都指向相同的內(nèi)存,每次拷貝都會(huì)觸發(fā)引用計(jì)數(shù)+1,每次生命周期結(jié)束析構(gòu)的時(shí)候引用計(jì)數(shù)-1,在最后一個(gè)shared_ptr析構(gòu)的時(shí)候,內(nèi)存才會(huì)釋放。 使用方法如下: struct ClassWrapper { ClassWrapper() { cout << 'construct' << endl; data = new int[10]; } ~ClassWrapper() { cout << 'deconstruct' << endl; if (data != nullptr) { delete[] data; } } void Print() { cout << 'print' << endl; } int* data; };
void Func(std::shared_ptr<ClassWrapper> ptr) { ptr->Print(); }
int main() { auto smart_ptr = std::make_shared<ClassWrapper>(); auto ptr2 = smart_ptr; // 引用計(jì)數(shù)+1 ptr2->Print(); Func(smart_ptr); // 引用計(jì)數(shù)+1 smart_ptr->Print(); ClassWrapper *p = smart_ptr.get(); // 可以通過get獲取裸指針 p->Print(); return 0; } 智能指針還可以自定義刪除器,在引用計(jì)數(shù)為0的時(shí)候自動(dòng)調(diào)用刪除器來(lái)釋放對(duì)象的內(nèi)存,代碼如下: std::shared_ptr<int> ptr(new int, [](int *p){ delete p; }); 關(guān)于shared_ptr有幾點(diǎn)需要注意: · 不要用一個(gè)裸指針初始化多個(gè)shared_ptr,會(huì)出現(xiàn)double_free導(dǎo)致程序崩潰 · 通過shared_from_this()返回this指針,不要把this指針作為shared_ptr返回出來(lái),因?yàn)閠his指針本質(zhì)就是裸指針,通過this返回可能 會(huì)導(dǎo)致重復(fù)析構(gòu),不能把this指針交給智能指針管理。 class A { shared_ptr<A> GetSelf() { return shared_from_this(); // return shared_ptr<A>(this); 錯(cuò)誤,會(huì)導(dǎo)致double free } };
上面代碼,產(chǎn)生了循環(huán)引用,導(dǎo)致aptr和bptr的引用計(jì)數(shù)為2,離開作用域后aptr和bptr的引用計(jì)數(shù)-1,但是永遠(yuǎn)不會(huì)為0,導(dǎo)致指針永遠(yuǎn)不會(huì)析構(gòu),產(chǎn)生了內(nèi)存泄漏,如何解決這種問題呢,答案是使用weak_ptr。 weak_ptrweak_ptr是用來(lái)監(jiān)視shared_ptr的生命周期,它不管理shared_ptr內(nèi)部的指針,它的拷貝的析構(gòu)都不會(huì)影響引用計(jì)數(shù),純粹是作為一個(gè)旁觀者監(jiān)視shared_ptr中管理的資源是否存在,可以用來(lái)返回this指針和解決循環(huán)引用問題。
struct A; struct B;
struct A { std::shared_ptr<B> bptr; ~A() { cout << 'A delete' << endl; } void Print() { cout << 'A' << endl; } };
struct B { std::weak_ptr<A> aptr; // 這里改成weak_ptr ~B() { cout << 'B delete' << endl; } void PrintA() { if (!aptr.expired()) { // 監(jiān)視shared_ptr的生命周期 auto ptr = aptr.lock(); ptr->Print(); } } };
int main() { auto aaptr = std::make_shared<A>(); auto bbptr = std::make_shared<B>(); aaptr->bptr = bbptr; bbptr->aptr = aaptr; bbptr->PrintA(); return 0; } 輸出: A A delete B delete unique_ptr std::unique_ptr是一個(gè)獨(dú)占型的智能指針,它不允許其它智能指針共享其內(nèi)部指針,也不允許unique_ptr的拷貝和賦值。使用方法和shared_ptr類似,區(qū)別是不可以拷貝:
unique_ptr也可以像shared_ptr一樣自定義刪除器,使用方法和shared_ptr相同。 關(guān)于c++11的智能指針的使用就介紹到這里,大家有問題可以點(diǎn)此留言 ,我會(huì)盡快回復(fù)~ 參考資料
|
|
來(lái)自: 西北望msm66g9f > 《編程》